You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中能否无需用户交互自动填充OTP至6个独立输入框?

实现iOS自动填充OTP到6个独立文本框

我刚好做过类似的需求,知道oneTimeCode默认需要用户手动粘贴的痛点,给你分享两个可行的方案,实现无需用户交互的自动填充:

方案一:系统OTP检测+隐藏文本桥接

这是最简洁的方案,利用系统自带的OTP识别能力,搭配一个隐藏的文本框来接收自动填充的内容,再拆分到6个可见文本框中:

  1. 创建隐藏的OTP接收文本框
    这个文本框必须加入视图层级(哪怕隐藏),系统才能识别它的oneTimeCode类型并自动填充OTP。我们监听它的文本变化事件,一旦有内容就拆分到可见文本框:

    // 隐藏的OTP接收器
    private let hiddenOTPField: UITextField = {
        let field = UITextField()
        field.textContentType = .oneTimeCode
        field.isHidden = true
        field.addTarget(self, action: #selector(handleOTPReceived(_:)), for: .editingChanged)
        return field
    }()
    
    // 存储6个可见的OTP输入框
    private var visibleOTPFields: [UITextField] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 一定要把隐藏文本框加到视图里
        view.addSubview(hiddenOTPField)
        // 这里初始化并添加6个可见文本框到视图...
    }
    
    @objc private func handleOTPReceived(_ textField: UITextField) {
        guard let otpCode = textField.text, otpCode.count == 6 else { return }
        // 拆分OTP到每个可见文本框
        for (index, char) in otpCode.enumerated() {
            guard index < visibleOTPFields.count else { break }
            visibleOTPFields[index].text = String(char)
            // 自动移动焦点,提升用户体验
            if index < visibleOTPFields.count - 1 {
                visibleOTPFields[index + 1].becomeFirstResponder()
            } else {
                visibleOTPFields[index].resignFirstResponder()
            }
        }
    }
    
  2. 联动处理用户手动输入
    给6个可见文本框设置代理,处理手动输入时的焦点跳转,同时同步更新隐藏文本框的内容:

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        // 处理删除操作,自动跳转到上一个框
        if string.isEmpty {
            guard let currentIndex = visibleOTPFields.firstIndex(of: textField), currentIndex > 0 else {
                textField.text = ""
                return false
            }
            textField.text = ""
            visibleOTPFields[currentIndex - 1].becomeFirstResponder()
            return false
        }
        // 只允许输入单个数字
        guard string.count == 1, CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: string)) else {
            return false
        }
        textField.text = string
        // 输入完成后跳转到下一个框
        if let currentIndex = visibleOTPFields.firstIndex(of: textField), currentIndex < visibleOTPFields.count - 1 {
            visibleOTPFields[currentIndex + 1].becomeFirstResponder()
        } else {
            textField.resignFirstResponder()
        }
        // 同步更新隐藏文本框的内容
        hiddenOTPField.text = visibleOTPFields.compactMap { $0.text }.joined()
        return false
    }
    

方案二:CoreTelephony监听短信(可选)

如果你的应用需要更主动的OTP获取,可以用CoreTelephony框架监听短信内容,提取OTP后自动填充。不过这个方案需要用户授权短信权限,还要处理不同运营商的短信格式,复杂度较高,一般推荐方案一。

注意事项

  • 记得在Info.plist中添加相关配置,帮助系统识别OTP短信,比如添加NSUserActivityTypes包含INSendMessageIntent;
  • 测试必须用真实设备,模拟器无法触发系统OTP自动填充功能。

内容的提问来源于stack exchange,提问作者Jagajith Monappan Kalarickal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 12:37:45