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

iOS17下SwiftUI键盘无法正常收起的问题排查求助

iOS17下SwiftUI键盘无法正常收起的解决方案

在iOS17模拟器及真机环境中,使用SwiftUI时遇到键盘无法正常收起的问题:按预期将focusedField设为nil无法收起键盘,调用resignFirstResponder的自定义方法后,键盘仅闪烁但保持弹出状态。问题代码如下:

import SwiftUI

struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme
    @FocusState private var focusedField: Field?
    @State private var lastname: String = ""

    enum Field: Hashable {
        case lastName
    }

    var body: some View {
        VStack {
            HStack {
                TextField("Last name", text: $lastname)
                    .disableAutocorrection(true)
                    .foregroundColor(Color.primary)
                    .autocapitalization(.words)
                    .textContentType(.familyName)
                    .focused($focusedField, equals: .lastName)
                    .submitLabel(.done)
                    .onSubmit {
                        focusedField = nil
                        dismissKeyboard()
                    }
                    .onTapGesture {
                        focusedField = .lastName
                    }
                Spacer()
            }
            .frame(height: 40)
            .overlay(
                Rectangle() // This creates the underline effect
                    .frame(height: 0.75)
                    .foregroundColor(colorScheme == .dark ? .white : .black)
                    .padding(.top, 30)
            )
            .padding()
        }
    }

    private func dismissKeyboard() {
        UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

问题原因

你给TextField添加的onTapGesture手动设置focusedField = .lastName,在iOS17的事件处理机制下,会和onSubmit里的键盘收起逻辑产生冲突:当点击完成按钮触发onSubmit后,可能因为UI事件的延迟传递,onTapGesture的逻辑被意外触发,重新将焦点赋予输入框,导致键盘无法收起。另外,TextField本身默认支持点击获取焦点,手动添加的onTapGesture属于冗余操作,反而干扰了SwiftUI的焦点管理流程。

解决方案

方案1:移除冗余的onTapGesture

直接删除TextField上的.onTapGesture修饰符,让TextField使用默认的焦点获取逻辑,此时仅通过focusedField = nil即可正常收起键盘:

修改后的核心代码:

TextField("Last name", text: $lastname)
    .disableAutocorrection(true)
    .foregroundColor(Color.primary)
    .autocapitalization(.words)
    .textContentType(.familyName)
    .focused($focusedField, equals: .lastName)
    .submitLabel(.done)
    .onSubmit {
        focusedField = nil
    }

方案2:使用更可靠的键盘收起方法(保留onTapGesture场景)

如果确实需要保留onTapGesture的自定义逻辑,可以替换原有的dismissKeyboard方法,使用UIApplication.shared.endEditing(true)来强制收起键盘,该方法会让所有当前处于第一响应者状态的控件 resign,避免焦点冲突:

修改后的代码:

private func dismissKeyboard() {
    UIApplication.shared.endEditing(true)
}

// 同时onSubmit可以简化为
.onSubmit {
    focusedField = nil
    dismissKeyboard()
}

验证效果

修改后在iOS17模拟器和真机上测试,点击输入框完成按钮,键盘可以正常收起,不会出现闪烁或无法关闭的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 03:52:19