Swift3 iOS中UITextField仅允许数字和点并添加%符号的实现问题
解决方案:实时添加%符号并保持输入验证
看起来你已经搞定了数字和小数点的输入限制,接下来要实现编辑时自动添加%符号的话,核心是要避免重复添加%、保持光标位置正确,同时不破坏现有的验证逻辑。我帮你修改了代码,直接替换原方法即可:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { // 处理删除操作:直接允许并同步更新文本与光标 if string.isEmpty { let originalText = textField.text?.replacingOccurrences(of: " %", with: "") ?? "" let newNumberString = (originalText as NSString).replacingCharacters(in: range, with: string) // 空字符串时不显示%,否则重新添加 textField.text = newNumberString.isEmpty ? "" : "\(newNumberString) %" // 把光标定位到数字末尾 let cursorOffset = newNumberString.count if let cursorPosition = textField.position(from: textField.beginningOfDocument, offset: cursorOffset) { textField.selectedTextRange = textField.textRange(from: cursorPosition, to: cursorPosition) } return false } guard textField == self.questionTextFeild else { return true } do { // 先移除原文本中的%,避免干扰验证逻辑 let originalText = textField.text?.replacingOccurrences(of: " %", with: "") ?? "" let newNumberString = (originalText as NSString).replacingCharacters(in: range, with: string) let expression = "^([0-9]+)?(\\.([0-9]{1,8})?)?$" let regex = try NSRegularExpression(pattern: expression, options: .caseInsensitive) let checkRange = NSRange(location: 0, length: newNumberString.utf16.count) let numberOfMatches = regex.numberOfMatches(in: newNumberString, options: [], range: checkRange) if numberOfMatches == 0 { return false } // 验证通过后,更新文本并添加% textField.text = "\(newNumberString) %" // 修正光标位置,确保在数字末尾(%前面) let cursorOffset = newNumberString.count if let cursorPosition = textField.position(from: textField.beginningOfDocument, offset: cursorOffset) { textField.selectedTextRange = textField.textRange(from: cursorPosition, to: cursorPosition) } // 返回false,因为我们已经手动处理了文本替换 return false } catch { print("Regex error: \(error.localizedDescription)") return false } }
关键细节说明:
- 避免重复%:每次处理输入前都会移除原文本中的" %",确保无论怎么编辑,末尾只会保留一个%符号。
- 光标体验优化:更新文本后自动把光标定位到数字部分的末尾,用户输入时不会被%符号干扰,操作更流畅。
- 删除逻辑兼容:删除字符到空时,文本会自动清空,不会出现空的" %"占位。
- 原验证逻辑保留:完全沿用你原来的正则规则,确保只能输入数字和最多一位小数点、小数点后最多8位数字。
测试一下这些场景:
- 输入"1" → 实时显示"1 %",光标停在"1"后面
- 输入"1.23" → 显示"1.23 %",光标停在"3"后面
- 删除所有字符 → 文本清空
- 输入"18.345" → 显示"18.345 %"
内容的提问来源于stack exchange,提问作者user2786
相关产品推荐
相关产品推荐

