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

SwiftUI中无需UIApplication.shared关闭键盘的方法(含应用扩展场景)

在SwiftUI应用扩展中关闭键盘(无需UIApplication.shared)

因为应用扩展无法访问UIApplication.shared,可以用以下几种原生SwiftUI或适配性方法实现键盘关闭:

方法1:使用@FocusState(推荐)

这是SwiftUI 3.0+提供的原生焦点管理API,完全不需要依赖UIKit的全局对象,非常适合应用扩展场景。

步骤:

  • 定义一个@FocusState属性,标记当前是否有输入框处于焦点状态
  • 将输入控件(如TextField、SecureField)与这个属性绑定
  • 需要关闭键盘时,将该属性设为nil即可

示例代码:

struct ExtensionContentView: View {
    @State private var inputText = ""
    @FocusState private var isInputFocused: Bool
    
    var body: some View {
        VStack {
            TextField("输入内容", text: $inputText)
                .focused($isInputFocused)
            
            Button("关闭键盘") {
                isInputFocused = false
            }
        }
    }
}

方法2:通过UIViewRepresentable包装实现

如果需要支持更低版本的SwiftUI,或者需要更灵活的控制,可以通过包装UIKit的UIResponder能力来实现:

创建一个自定义的DismissKeyboardViewModifier,利用UIView的endEditing(_:)方法关闭键盘:

struct DismissKeyboardViewModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .background(
                UIViewRepresentable { uiView in
                    let tapGesture = UITapGestureRecognizer(target: uiView, action: #selector(uiView.endEditing(_:)))
                    uiView.addGestureRecognizer(tapGesture)
                }
            )
    }
}

extension View {
    func dismissKeyboardOnTap() -> some View {
        self.modifier(DismissKeyboardViewModifier())
    }
}

// 使用方式
struct ExtensionContentView: View {
    @State private var inputText = ""
    
    var body: some View {
        VStack {
            TextField("输入内容", text: $inputText)
        }
        .dismissKeyboardOnTap()
    }
}

这个方法通过给视图添加点击手势,触发endEditing(true)来关闭当前所有活跃的键盘,同样不需要访问UIApplication。

方法3:利用NotificationCenter(适合特定场景)

如果需要在某个全局事件触发时关闭键盘,可以通过发送自定义通知,在输入控件的代理中监听并关闭:

// 定义通知名称
extension Notification.Name {
    static let dismissKeyboard = Notification.Name("DismissKeyboardNotification")
}

// 包装TextField并监听通知
struct DismissibleTextField: UIViewRepresentable {
    @Binding var text: String
    
    func makeUIView(context: Context) -> UITextField {
        let textField = UITextField()
        textField.delegate = context.coordinator
        NotificationCenter.default.addObserver(context.coordinator, selector: #selector(Coordinator.dismissKeyboard), name: .dismissKeyboard, object: nil)
        return textField
    }
    
    func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = text
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(text: $text)
    }
    
    class Coordinator: NSObject, UITextFieldDelegate {
        @Binding var text: String
        
        init(text: Binding<String>) {
            _text = text
        }
        
        func textFieldDidChangeSelection(_ textField: UITextField) {
            text = textField.text ?? ""
        }
        
        @objc func dismissKeyboard() {
            textField.resignFirstResponder()
        }
    }
}

// 使用时发送通知关闭键盘
Button("关闭键盘") {
    NotificationCenter.default.post(name: .dismissKeyboard, object: nil)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 12:12:19