美文网首页
UITextField电话号码输入框格式 xxx xxxx xx

UITextField电话号码输入框格式 xxx xxxx xx

作者: 九龙 | 来源:发表于2019-10-11 17:51 被阅读0次

    问题:
    项目中需要设置电话号码输入时如xxx xxxx xxxx的格式

    自定义控件代码:

    import UIKit
    
    class PhoneField: UITextField {
        
        //保存上一次的文本内容
        var _previousText:String!
        
        //保持上一次的文本范围
        var _previousRange:UITextRange!
        
        override init(frame: CGRect) {
            super.init(frame: frame)
            setupUI()
        }
        
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            setupUI()
        }
    
        func setupUI() {
            //默认边框样式为圆角矩形
            self.borderStyle = UITextField.BorderStyle.none
            //使用数字键盘
            self.keyboardType = UIKeyboardType.numberPad
        }
        
        
        //当本视图的父类视图改变的时候
        override func willMove(toSuperview newSuperview: UIView?) {
            //监听值改变通知事件
            if newSuperview != nil {
                NotificationCenter.default.addObserver(self,
                                                       selector: #selector(phoneNumberFormat(_:)),
                                                       name: UITextField.textDidChangeNotification,
                                                       object: nil)
            }else{
                NotificationCenter.default.removeObserver(self,
                                                          name: UITextField.textDidChangeNotification,
                                                          object: nil)
            }
        }
        
        //输入框内容改变时对其内容做格式化处理
        @objc func phoneNumberFormat(_ notification: Notification) {
            let textField = notification.object as! UITextField
            
            if(!textField.isEqual(self)){ return }
            
            guard let selectedTextRange = textField.selectedTextRange else { return }
            
            //当前光标的位置(后面会对其做修改)
            var cursorPostion = textField.offset(from: textField.beginningOfDocument,
                                                 to: selectedTextRange.start)
            
            //过滤掉非数字字符,只保留数字
            let digitsText = getDigitsText(string: textField.text!,
                                           cursorPosition: &cursorPostion)
            
            //避免超过11位的输入
            if digitsText.count > 11 {
                textField.text = _previousText
                textField.selectedTextRange = _previousRange
                return
            }
            
            //得到带有分隔符的字符串
            let hyphenText = getHyphenText(string: digitsText, cursorPosition: &cursorPostion)
            
            //将最终带有分隔符的字符串显示到textField上
            textField.text = hyphenText
            
            //让光标停留在正确位置
            guard let targetPostion = textField.position(from: textField.beginningOfDocument,
                                                         offset: cursorPostion) else{ return }
            textField.selectedTextRange = textField.textRange(from: targetPostion,
                                                              to: targetPostion)
            
            //现在的值和选中范围,供下一次输入使用
            _previousText = self.text!
            _previousRange = selectedTextRange
        }
        
        //除去非数字字符,同时确定光标正确位置
        func getDigitsText(string:String, cursorPosition:inout Int) -> String{
            //保存开始时光标的位置
            let originalCursorPosition = cursorPosition
            //处理后的结果字符串
            var result = ""
            
            var i = 0
            //遍历每一个字符
            for uni in string.unicodeScalars {
                //如果是数字则添加到返回结果中
                if CharacterSet.decimalDigits.contains(uni) {
                    result.append(string[i])
                }
                    //非数字则跳过,如果这个非法字符在光标位置之前,则光标需要向前移动
                else{
                    if i < originalCursorPosition {
                        cursorPosition = cursorPosition - 1
                    }
                }
                i = i + 1
            }
            
            return result
        }
        
        //将分隔符插入现在的string中,同时确定光标正确位置
        func getHyphenText(string:String, cursorPosition:inout Int) -> String {
            //保存开始时光标的位置
            let originalCursorPosition = cursorPosition
            //处理后的结果字符串
            var result = ""
            
            //遍历每一个字符
            for i in 0  ..< string.count  {
                //如果当前到了第4个、第8个数字,则先添加个分隔符
                if i == 3 || i == 7 {
                    result.append(" ")
                    //如果添加分隔符位置在光标前面,光标则需向后移动一位
                    if i < originalCursorPosition {
                        cursorPosition = cursorPosition + 1
                    }
                }
                result.append(string[i])
            }
            
            return result
        }
    }
    
    //通过对String扩展,字符串增加下表索引功能
    extension String
    {
        subscript(index:Int) -> String
        {
            get{
                return String(self[self.index(self.startIndex, offsetBy: index)])
            }
            set{
                let tmp = self
                self = ""
                for (idx, item) in tmp.enumerated() {
                    if idx == index {
                        self += "\(newValue)"
                    }else{
                        self += "\(item)"
                    }
                }
            }
        }
    }
    
    

    上面的代码只能根据输入改变格式,如果直接设置号码的话就会无用
    这时候可以用NumberFormatter
    下面为解决方法

    private lazy var phoneFormatter:NumberFormatter = {
            let _formatter = NumberFormatter.init()
            _formatter.groupingSeparator = " "
            _formatter.groupingSize = 4
            _formatter.usesGroupingSeparator = true
            return _formatter
        }()
    调用:
    phoneTextField.text = phoneFormatter.string(from: NSNumber.init(value:"12345678901"))
    
    

    记得点赞哦

    相关文章

      网友评论

          本文标题:UITextField电话号码输入框格式 xxx xxxx xx

          本文链接:https://www.haomeiwen.com/subject/ihjxmctx.html