iOS Swift:OTP式手机号输入框空值退格焦点跳转问题处理
解决OTP输入框空状态下退格键跳转问题
问题根源
当前代码依赖输入框文本内容判断退格键,当输入框为空时,文本为空字符串,导致退格键的判断逻辑失效,无法触发跳转到上一个输入框的操作。
优化方案
通过数组统一管理输入框,简化索引操作;在shouldChangeCharactersIn方法中准确处理输入和退格场景,尤其是空输入框的退格逻辑。
完整修改代码
@IBOutlet weak var textFieldNumber1: UITextField! @IBOutlet weak var textFieldNumber2: UITextField! @IBOutlet weak var textFieldNumber3: UITextField! @IBOutlet weak var textFieldNumber4: UITextField! @IBOutlet weak var textFieldNumber5: UITextField! @IBOutlet weak var textFieldNumber6: UITextField! @IBOutlet weak var textFieldNumber7: UITextField! @IBOutlet weak var textFieldNumber8: UITextField! @IBOutlet weak var textFieldNumber9: UITextField! @IBOutlet weak var textFieldNumber10: UITextField! @IBOutlet weak var textFieldPassword: UITextField! private var otpTextFields: [UITextField]! private var counterTextFieldPhoneNumber = 0 func setupTextFields() { // 将输入框整理为数组,方便索引操作 otpTextFields = [textFieldNumber1, textFieldNumber2, textFieldNumber3, textFieldNumber4, textFieldNumber5, textFieldNumber6, textFieldNumber7, textFieldNumber8, textFieldNumber9, textFieldNumber10].compactMap { $0 } otpTextFields.forEach { tf in tf.keyboardType = .numberPad tf.delegate = self tf.tag = otpTextFields.firstIndex(of: tf)! + 1 // 保持tag从1开始,兼容原有逻辑 } } func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { // 处理数字输入:仅允许单个数字字符 if !string.isEmpty { guard textField.text?.isEmpty ?? true else { return false } // 已有内容时不允许重复输入 textField.text = string counterTextFieldPhoneNumber += 1 // 跳转到下一个输入框(如果不是最后一个) let currentIndex = otpTextFields.firstIndex(of: textField)! if currentIndex < otpTextFields.count - 1 { otpTextFields[currentIndex + 1].becomeFirstResponder() } else { // 最后一个输入框完成,收起键盘并拼接手机号 textField.resignFirstResponder() let phoneNumber = otpTextFields.compactMap { $0.text }.joined() viewModel.phoneNumber = phoneNumber } return false } else { // 处理退格键操作 if textField.text?.isEmpty ?? true { // 当前输入框为空,跳转到上一个输入框(如果存在) let currentIndex = otpTextFields.firstIndex(of: textField)! if currentIndex > 0 { let previousTF = otpTextFields[currentIndex - 1] previousTF.text = "" previousTF.becomeFirstResponder() counterTextFieldPhoneNumber = max(0, counterTextFieldPhoneNumber - 1) } else { // 第一个输入框为空,退格不触发跳转,仅修正计数器 counterTextFieldPhoneNumber = max(0, counterTextFieldPhoneNumber - 1) } } else { // 当前输入框有内容,清空内容并修正计数器 textField.text = "" counterTextFieldPhoneNumber = max(0, counterTextFieldPhoneNumber - 1) } return false } }
关键改进点
- 数组化管理输入框:替代大量switch分支,通过索引直接定位上/下一个输入框,代码更简洁易维护。
- 精准退格判断:通过
replacementString.isEmpty判断退格操作,不受输入框是否为空的影响,逻辑更可靠。 - 空输入框退格处理:空输入框触发退格时,自动跳转到上一个输入框并清空其内容(如需保留内容可移除
previousTF.text = ""),符合用户操作习惯。 - 简化输入逻辑:输入单个数字后自动跳转下一个输入框,最后一个输入完成后自动收起键盘并拼接手机号。
内容的提问来源于stack exchange,提问作者Shaikh
相关产品推荐
相关产品推荐

