在项目中遇到一个这样的需求
1、只允许用户输入中英文数字 2、最多只能输入6个中文 3、最多只能输入12个英文或数字 4、中英混排总长度不超过12(中文长度2,英文或数字长度1)
搜了一下网上的解决方法,找到了两篇关于这个的方法,因此记录下来,方便日后直接使用。为了方便,都写成了extension方便调用
https://www.jianshu.com/p/0e4c32638c37 https://www.jianshu.com/p/4c621f509432
extension String {
/// 或者字符串的字节长度 中文-2,英文1
func getStringLengthOfBytes() -> Int {
var length = 0
for i in 0..<self.count {
let subStr = (self as NSString).substring(with: NSMakeRange(i, 1))
if subStr.validateChinese() {
length += 2
}else {
length += 1
}
}
return length
}
/// 根据索引获取子字符串,长度以字节长度(中文-2,英文1)计算
func subBytesOfStringTo(index: Int) -> String {
var length = 0
var chineseNum = 0
var zifuNum = 0
for i in 0..<self.count {
let subStr = (self as NSString).substring(with: NSMakeRange(i, 1))
if subStr.validateChinese() {
if length + 2 > index {
return self.subStringTo(chineseNum + zifuNum)
}
length += 2
chineseNum += 1
}else {
if length + 1 > index {
return self.subStringTo(chineseNum + zifuNum)
}
length += 1
zifuNum += 1
}
}
return self.subStringTo(index)
}
/// 检测中文
func validateChinese() -> Bool {
let pattern = "[\\u4e00-\\u9fa5]"
return self.isMatchRegularExp(pattern)
}
/// 是否匹配正则
func isMatchRegularExp(_ pattern: String) -> Bool {
guard let reg = try? NSRegularExpression(pattern: pattern, options: NSRegularExpression.Options.caseInsensitive) else {
return false
}
let result = reg.matches(in: self, options: .reportProgress, range: NSMakeRange(0, self.length))
return (result.count > 0)
}
}
使用UIControlEvents的editingChanged进行监听。其中需要特别处理的就是中文的输入,例如输入“黄河之水天上来”,在输入框显示“huanghezhishuitianshanglai”的时候,就会限制输入了,因此通过textField.markedTextRange
判断是否有选中框存在(中文输入时,有选中框)
@objc fileprivate func textChange(textField: UITextField) {
let maxLength = 12
let text = textField.text ?? ""
guard let mode = textField.textInputMode?.primaryLanguage else {
return
}
// 简体中文输入,包括简体拼音,健体五笔,简体手写
if mode == "zh-Hans" {
if let selectedRange = textField.markedTextRange {
//获取高亮部分
if textField.position(from: selectedRange.start, offset: 0) == nil {
if text.getStringLengthOfBytes() > maxLength {
textField.text = text.subBytesOfStringTo(index: maxLength)
}
}
}else {
if text.getStringLengthOfBytes() > maxLength {
textField.text = text.subBytesOfStringTo(index: maxLength)
}
}
}else {
if text.getStringLengthOfBytes() > maxLength {
textField.text = text.subBytesOfStringTo(index: maxLength)
}
}
}
通过UITextField的代理shouldChangeCharactersIn
,进行判断
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let pattern = "[a-zA-Z\\u4E00-\\u9FA5\\u0030-\\u0039]"
return string.isMatchRegularExp(pattern) || string.isEmpty
}