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

SwiftUI iOS 17中TextField无法粘贴键盘建议OTP的问题求助

iOS 17 SwiftUI OTP键盘建议首次点击失效问题解决

问题现象

  • SwiftUI开发的iOS应用中,键盘提供的一次性密码(OTP)建议偶尔出现首次点击无法粘贴到输入框的情况,二次点击则总能成功
  • 该问题仅在iOS 17设备上出现,iOS 15、16版本无此异常

问题原因

iOS 17对TextField的OTP填充逻辑做了调整,当前代码存在两个干扰系统填充流程的点:

  1. onChange(of: code)会在输入内容变化时立即触发submitCode(),可能在系统还未完成OTP粘贴时就修改输入框状态或截断内容
  2. 当code长度达到6位时立即禁用输入框,导致系统首次填充OTP时输入框状态异常,无法正确写入值

解决方案

  1. 给submitCode()添加延迟执行,让系统有足够时间完成OTP填充
  2. 调整输入框禁用逻辑,避免在填充过程中修改状态
  3. 优化onChange的触发条件,避免重复执行提交逻辑

修改后的关键代码

private var codeBackgroundField: some View {
    TextField("", text: $code, onCommit: submitCode)
        .font(.system(size: 35))
        .accentColor(.clear) // 隐藏iOS 15光标
        .tint(.clear) // 隐藏iOS 16+光标
        .foregroundColor(.clear)
        .textContentType(.oneTimeCode)
        .keyboardType(.numberPad)
        .disabled(isDisabled)
        // 仅当code长度稳定后再触发提交,避免填充过程中重复调用
        .onChange(of: code) { newValue in
            guard newValue.count <= maxDigits else {
                code = String(newValue.suffix(maxDigits))
                return
            }
            if newValue.count == maxDigits {
                // 延迟执行,给系统OTP填充留足时间
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
                    submitCode()
                }
            }
        }
}

private func submitCode() {
    guard code.count == maxDigits else { return }
    
    UIApplication.shared.closeKeyboard()
    isDisabled = true

    onFinishedEntry(code) { verifiedCode in
        DispatchQueue.main.async {
            if !verifiedCode {
                code = ""
            }
            isDisabled = false
        }
    }
}

额外说明

延迟时间可根据实际测试情况调整,确保系统完成OTP填充后再执行提交逻辑。也可以尝试移除disabled状态的立即设置,改为在验证完成后再处理输入框状态,进一步避免干扰填充流程。

内容的提问来源于stack exchange,提问作者wristbands

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 16:03:13