iOS 中的 UITextField 如何设置才能只输入数字和小数点?

刚接触 iOS不久,接到一个iOS项目,其中有一个需求就是在一个 UITextField中只能输入数字和小数点,这个需求在Android中非常容易,只需要设置

 <EditText
                    android:id="@+id/id_et_price"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:ellipsize="end"
                    android:inputType="numberDecimal"
                    android:lines="1"
                    android:singleLine="true" />

只需要设置 android:inputType="numberDecimal" 即可。
我原本以为 iOS 应该也很简单,然后问了一下 gpt, 果然也是类似的配置:

textField.keyboardType = .numberPad

如果允许小数点,那么就可以使用

textField.keyboardType = .decimalPad

当然,这是最基本的,但是 iOS 中比较坑爹的是,如果用户使用外接键盘或者复制粘贴,仍然可以输入非数字字符。什么意思呢?,假如我们现在复制了一个 “23.34元”, 现在我可以粘贴到 UITextField中,那么不能输入数字的UITextField仍然可以输入,且显示为”23.34元“,最后我们提交数据时,就会产生问题。

如何解决这个问题呢?其实解决方案也比较多,这里我给出一种比较常见的解决方案,就是直接继承自UITextField,对paste 事件进行监听,对输入的字符串进行校验, 非数字和小数点字符直接去掉。

class NumericTextField : UITextField {
    
    override func awakeFromNib() {
        super.awakeFromNib()
        
        self.keyboardType = .numberPad
        
        self.delegate = self
    }
    
    override func paste(_ sender: Any?) {
        
        if let pasteboardString = UIPasteboard.general.string {
                        
            //创建一个字符集包含数字和小数点
            let allowedCharacterSet = CharacterSet(charactersIn: ".0123456789")
            
            //使用字符集分割字符串,移除不在字符中的字符
            let filteredString = pasteboardString.components(separatedBy: allowedCharacterSet.inverted).joined()
                                                
            if let _ = Float(filteredString), !filteredString.isEmpty {
                                
                if let selectedRange = self.selectedTextRange {
                    
                    self.replace(selectedRange, withText: filteredString)
                    
                }
            }
        }
    }
}

extension NumericTextField : UITextFieldDelegate {
        
    func textField(_ textField: UITextField, 
                   shouldChangeCharactersIn range: NSRange,
                   replacementString string: String) -> Bool {
        
        if(string.isEmpty) {
            return true 
        }
        
        // 检查输入的字符是否是数字
        let allowedCharacters = CharacterSet(charactersIn: ".0123456789")
        let characterSet = CharacterSet(charactersIn: string)
        return allowedCharacters.isSuperset(of: characterSet)
    }
    
}

那么用起来直接可以使用 NumericTextField 替代 UITextField 即可。

最近更新

  1. TCP协议是安全的吗?

    2024-03-10 04:20:04       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-10 04:20:04       18 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-10 04:20:04       17 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-10 04:20:04       20 阅读

热门阅读

  1. ChatGPT 新增朗读功能,支持 37 种语言

    2024-03-10 04:20:04       24 阅读
  2. Oracle数据库日志文件

    2024-03-10 04:20:04       22 阅读
  3. 某IC交易网 js逆向解析学习【2024/03/7】更新

    2024-03-10 04:20:04       21 阅读
  4. 微信小程序 提交表单

    2024-03-10 04:20:04       18 阅读
  5. MySQL时间类型和Mybatis处理

    2024-03-10 04:20:04       23 阅读
  6. 算法-跳跃游戏 II

    2024-03-10 04:20:04       24 阅读
  7. Redis优化与应用

    2024-03-10 04:20:04       22 阅读
  8. 设计模式—单例模式

    2024-03-10 04:20:04       20 阅读