iOS开发实战 - 准确限制UITextView的输入字数
2019-12-19 本文已影响0人
ArchLL
系统版本:iOS 8.0+
语言版本:swift 5.0
输入模式:简体中文、繁体中文、English(US)
字符支持:暂不支持emoji
等特殊字符的字数的准确限制
知识延展:UITextField
也可以在相关代理方法中用下面的做法限制输入字数
/// 是否需要将textView的光标定位到尾部
private var isLocationToEnd: Bool = false
// MARK:- UITextViewDelegate
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == "" { // 删除字数
return true
}
let inputMode = UITextInputMode.activeInputModes.first?.primaryLanguage
if inputMode == "zh-Hans" || inputMode == "zh-Hant" { // 简体/繁体中文输入法(拼音、手写输入等)
if let selectedRange = textView.markedTextRange,
let _ = textView.position(from: selectedRange.start, offset: 0) { // 如果有高亮的文本,如拼音、手写
// 拼音输入:联想的过程中,location时刻变化(高亮文本的尾部位置),length始终为0
// 手写输入:联想的过程中不会回调该代理方法,确认联想词后才会进入该代理方法
if range.length > 0 { // 选中联想词后,location变回高亮文本的起始位置,length为高亮文本的长度,需要对字数限制字数
return !limitMaxWordsCount(textView, replacementText: text, isLocationToEnd: false)
}
} else { // 没有高亮选择的字,对已输入的文字进行字数限制
if range.location >= maxWordsCount {
SVProgressHUD.showError(withStatus: "最多可输入\(maxWordsCount)字")
return false
} else { // 处理粘贴引起的字数超限, 截取文本后需要自己去移动光标到尾部
return !limitMaxWordsCount(textView, replacementText: text, isLocationToEnd: true)
}
}
} else { // 中文输入法以外的输入法直接进行字数限制
if range.location >= maxWordsCount {
SVProgressHUD.showError(withStatus: "最多可输入\(maxWordsCount)字")
return false
} else { // 处理粘贴引起的字数超限, 截取文本后需要自己去移动光标到尾部
return !limitMaxWordsCount(textView, replacementText: text, isLocationToEnd: true)
}
}
return true
}
func textViewDidChangeSelection(_ textView: UITextView) {
if let text = textView.text, isLocationToEnd, text.utf16.count >= maxWordsCount {
textView.selectedRange = NSRange(location: maxWordsCount, length: 0)
isLocationToEnd = false
SVProgressHUD.showError(withStatus: "最多可输入\(maxWordsCount)字")
}
}
func limitMaxWordsCount(_ textView: UITextView, replacementText text: String, isLocationToEnd: Bool) -> Bool {
let string = textView.text + text
if string.utf16.count > maxWordsCount {
textView.text = String(string.prefix(maxWordsCount))
self.isLocationToEnd = isLocationToEnd
return true
}
return false
}
参考: