Swift中文输入法限制字数以及常用字符串处理方法

有个常用需求是这样:例如修改昵称时,要求输入不超过10个字符。(中英文数字都算一个字符)。如果用textField自带的textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool 这个代理方法的话,会有一个问题是这样。当使用中文输入法的时候,在输入拼音的时候,还没有选中汉字,你输入的拼音字母已经被统计在内了。这样就不符合需求。

上面的问题不论是OC还是Swift,解决思路是一样的。之前的项目里我直接把OC的内容翻译到Swift里面,发现直接翻译过来的会存在一些问题。下面我在代码里具体写一下解决思路以及遇到的问题的解决办法:


///首先注册通知
private func addNoti() {
        NotificationCenter.default.addObserver(self, selector: #selector(textFieldDidChange(noti:)), name: NSNotification.Name.UITextFieldTextDidChange, object: myTextFeild)
    }

    @objc func textFieldDidChange(noti: Notification) {
        if let field = noti.object as? UITextField {
            if let toBeString = field.text {
                ///键盘输入模式(OC里面通过[[UITextInputMode currentInputMode] primaryLanguage]来获取当前输入法,Swift里面没有currentInputMode这个东西,只能是获取你正在使用的所有输入法,然后第一个就是当前输入法)
                if let language = UITextInputMode.activeInputModes.first?.primaryLanguage {
                    if language == "zh-Hans" {///中文输入法
                        ///这里跟OC也有点区别,直接如下这么写就行,只有在输入拼音选中后才会走到else里面,然后在else里面写条件判断就好了
                        if let _ = field.markedTextRange {
                        }else {
                            if toBeString.length > 10 {
                                ///swift里面处理字符串特别麻烦,这里非要用String.index 这种类型,然后我给string常用的一些方法都封装了一下。这里直接这么调用就可以
                                field.text = toBeString.substring(to: 10)
                            }
                        }
                    }else {///非中文输入法,直接统计字数和限制,这里没有考虑其他语种的情况
                        if toBeString.length > 10 {
                            field.text = toBeString.substring(to: 10)
                        }
                    }
                }
            }
        }
    }

extension String {

    //MARK:-截取字符串从开始到 index
    func substring(to index: Int) -> String {
        guard let end_Index = validEndIndex(original: index) else {
            return self;
        }

        return String(self[startIndex..<end_Index]);
    }
    //MARK:-截取字符串从index到结束
    func substring(from index: Int) -> String {
        guard let start_index = validStartIndex(original: index)  else {
            return self
        }
        return String(self[start_index..<endIndex])
    }
    //MARK:-切割字符串(区间范围 前闭后开)
    func sliceString(_ range:CountableRange<Int>)->String{

        guard
            let startIndex = validStartIndex(original: range.lowerBound),
            let endIndex   = validEndIndex(original: range.upperBound),
            startIndex <= endIndex
            else {
                return ""
        }

        return String(self[startIndex..<endIndex])
    }
    //MARK:-切割字符串(区间范围 前闭后闭)
    func sliceString(_ range:CountableClosedRange<Int>)->String{

        guard
            let start_Index = validStartIndex(original: range.lowerBound),
            let end_Index   = validEndIndex(original: range.upperBound),
            startIndex <= endIndex
            else {
                return ""
        }
        if(endIndex.encodedOffset <= end_Index.encodedOffset){
            return String(self[start_Index..<endIndex])
        }
        return String(self[start_Index...end_Index])

    }
    //MARK:-校验字符串位置 是否合理,并返回String.Index
    private func validIndex(original: Int) -> String.Index {

        switch original {
        case ...startIndex.encodedOffset : return startIndex
        case endIndex.encodedOffset...   : return endIndex
        default                          : return index(startIndex, offsetBy: original)
        }
    }
    //MARK:-校验是否是合法的起始位置
    private func validStartIndex(original: Int) -> String.Index? {
        guard original <= endIndex.encodedOffset else { return nil }
        return validIndex(original:original)
    }
    //MARK:-校验是否是合法的结束位置
    private func validEndIndex(original: Int) -> String.Index? {
        guard original >= startIndex.encodedOffset else { return nil }
        return validIndex(original:original)
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值