Swift中UITextField实时转百分比格式化退格键失效问题求解
问题根因
当光标位于末尾%右侧时按下退格键,系统会先删除最后一个字符%,此时输入框临时文本为不带%的纯数字串。你的格式化方法会自动将纯数字再次补回%,且数字本身未发生变化,最终文本和修改前完全一致,看起来就像删除操作未生效。
解决方案
需要从三个方面调整代码:
1. 修正字符串格式化扩展
删除强制返回0%的逻辑,当纯数字为空时直接返回空字符串,避免删到最后一位时强制回弹为0%:
func percentInputFormatting() -> String { let formatter = NumberFormatter() formatter.numberStyle = .decimal formatter.maximumFractionDigits = 2 formatter.minimumFractionDigits = 2 // 过滤所有非数字字符 let regex = try! NSRegularExpression(pattern: "[^0-9]", options: .caseInsensitive) let pureNumberStr = regex.stringByReplacingMatches(in: self, options: [], range: NSMakeRange(0, self.count), withTemplate: "") // 纯数字为空直接返回空 guard !pureNumberStr.isEmpty else { return "" } let double = (pureNumberStr as NSString).doubleValue let number = NSNumber(value: double / 100) guard let formattedStr = formatter.string(from: number) else { return "0%" } return "\(formattedStr)%" }
2. 处理末尾退格特殊场景
给UITextField设置代理,实现shouldChangeCharactersIn方法,拦截光标在末尾时的退格操作,主动删除最后一位数字:
// 先给输入框设置代理 cell.textField.delegate = self // 实现代理方法 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { // 匹配:退格操作 + 光标在最后一位 + 当前文本以%结尾 if string.isEmpty, let currentText = textField.text, currentText.hasSuffix("%"), range.location == currentText.count - 1 { // 提取纯数字并删除最后一位后重新格式化 let regex = try! NSRegularExpression(pattern: "[^0-9]", options: .caseInsensitive) var pureNumberStr = regex.stringByReplacingMatches(in: currentText, options: [], range: NSMakeRange(0, currentText.count), withTemplate: "") pureNumberStr = String(pureNumberStr.dropLast(1)) textField.text = pureNumberStr.percentInputFormatting() return false } return true }
3. 优化光标位置(可选,提升体验)
在输入变更回调中,格式化完成后自动将光标移动到%符号前,避免用户每次都要手动移动光标:
@objc func textChangedIntoPercent (sender : UITextField) { if let amountString = sender.text?.percentInputFormatting() { sender.text = amountString // 将光标定位到%前面 if let position = sender.position(from: sender.endOfDocument, offset: -1) { sender.selectedTextRange = sender.textRange(from: position, to: position) } } }
内容的提问来源于stack exchange,提问作者user14664032
相关产品推荐
相关产品推荐

