Swift实现UITextField手机号输入时自动移除横杠保留纯数字
iOS UITextField 电话键盘实时过滤横杠、纯数字手机号输入实现方案
核心逻辑是在文本全量变更节点统一做字符过滤,覆盖手动输入、系统格式化插入横杠、QuickType推荐号码自动填充全场景,同时保证输入光标体验正常、11位长度限制生效。
实现要点
- 不要仅依赖
textField(_:shouldChangeCharactersIn:replacementString:)代理方法处理,该方法无法完整捕获iOS电话键盘自动插入横杠、系统推荐号码一键填充的所有触发时机,会出现过滤遗漏。 - 统一绑定
UIControl.editingChanged事件做处理,该事件会在所有文本变更动作完成后触发,覆盖所有输入来源。 - 过滤逻辑只保留0-9的十进制数字,移除所有横杠、空格、括号等非数字字符,同时做11位长度截断。
- 文本重新赋值后需要恢复光标位置,避免输入过程中光标自动跳到末尾打断操作。
核心代码(Swift)
1. 绑定编辑事件
// 初始化UITextField时调用,若使用Xib/Storyboard可直接拖线绑定editingChanged事件 phoneTextField.keyboardType = .phonePad phoneTextField.addTarget(self, action: #selector(handlePhoneInputChange(_:)), for: .editingChanged)
2. 文本变更处理逻辑
@objc private func handlePhoneInputChange(_ textField: UITextField) { guard let rawText = textField.text else { return } // 过滤所有非数字字符 let pureDigits = rawText .components(separatedBy: CharacterSet.decimalDigits.inverted) .joined() // 限制最大11位长度 let maxLength = 11 let resultText = pureDigits.count > maxLength ? String(pureDigits.prefix(maxLength)) : pureDigits // 记录当前光标偏移量,避免赋值后光标跳转到末尾 var cursorOffset: Int? if let selectedRange = textField.selectedTextRange { cursorOffset = textField.offset(from: textField.beginningOfDocument, to: selectedRange.start) } // 赋值处理后的纯数字文本 textField.text = resultText // 恢复光标位置 if let offset = cursorOffset { let safeOffset = min(offset, resultText.count) if let targetPosition = textField.position(from: textField.beginningOfDocument, offset: safeOffset) { textField.selectedTextRange = textField.textRange(from: targetPosition, to: targetPosition) } } }
兼容说明
- 手动输入过程中,系统电话键盘自动插入的横杠会在出现的瞬间被过滤,输入框全程只显示纯数字,不会出现横杠占位导致长度限制误判的问题
- 点击键盘上方QuickType栏推荐的联系人号码、触发iOS系统手机号自动填充时,无论原始号码格式带多少横杠、空格、国际区号前缀,都会被过滤为纯数字并自动截断到11位
- 支持在号码任意位置插入、删除数字,光标位置不会错乱,输入体验和原生无差异
注意:如果之前在
shouldChangeCharactersInRange代理中写了长度限制逻辑,请将该逻辑移除,统一放到上述editingChanged回调中处理,避免双重限制导致输入到第10位后无法继续输入的问题。
内容的提问来源于stack exchange,提问作者JJHA
相关产品推荐
相关产品推荐

