如何在不放弃第一响应者的情况下隐藏UITextView键盘并显示格式Sheet?
解决方案
核心思路
- 点击格式按钮时,先让UITextView放弃第一响应者身份收起键盘,再设置
inputView为空视图,随后重新成为第一响应者,以此保持编辑状态且不弹出键盘 - 格式Sheet关闭时,恢复
inputView为nil,确保后续输入能正常唤起原生键盘 - 修正原代码中UITextView作为struct存储属性的问题,避免值类型复制引发的异常
修改后的完整代码
struct EditorView: UIViewRepresentable { @ObservedObject var model: EditorModel init(model: EditorModel) { self.model = model } func makeUIView(context: Context) -> UITextView { let textView = UITextView() textView.allowsEditingTextAttributes = true textView.delegate = context.coordinator textView.keyboardDismissMode = .interactive textView.alwaysBounceVertical = true textView.font = .preferredFont(forTextStyle: .body) let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: textView.frame.size.width, height: 44)) let boldButton = UIBarButtonItem( title: "Format text", image: UIImage(systemName: "textformat"), primaryAction: UIAction(title: "Format text", handler: { _ in model.isTextFormatSheetVisible = true // 先收起键盘,再替换输入视图,重新获取第一响应者身份 textView.resignFirstResponder() textView.inputView = UIView() textView.becomeFirstResponder() }) ) toolBar.setItems([boldButton], animated: true) textView.inputAccessoryView = toolBar return textView } func updateUIView(_ textView: UITextView, context: Context) { textView.attributedText = model.attributedText textView.selectedRange = model.selectedRange // Sheet关闭时恢复输入视图,保证后续能正常唤起键盘 if !model.isTextFormatSheetVisible, textView.inputView != nil { textView.inputView = nil // 如果当前仍处于编辑状态,重新唤起键盘 if textView.isFirstResponder { textView.resignFirstResponder() textView.becomeFirstResponder() } } } func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, UITextViewDelegate { private var parent: EditorView init(_ parent: EditorView) { self.parent = parent } func textViewDidChange(_ textView: UITextView) { parent.model.attributedText = textView.attributedText parent.model.selectedRange = textView.selectedRange } func textViewDidChangeSelection(_ textView: UITextView) { DispatchQueue.main.async { self.parent.model.selectedRange = textView.selectedRange } } } }
关键细节说明
- 移除struct存储的UITextView:原代码将UITextView作为struct属性,因Swift struct是值类型,多次复制会导致异常,改为在
makeUIView内创建更符合UIViewRepresentable的生命周期规范 - 切换第一响应者状态:键盘弹出后直接修改
inputView无效,必须通过「放弃第一响应者→修改输入视图→重新获取第一响应者」的流程,才能让系统识别到输入视图的变化 - 恢复输入视图:Sheet关闭后必须将
inputView设回nil,否则后续输入无法唤起原生键盘
内容的提问来源于stack exchange,提问作者Nicola D'Aniello
相关产品推荐
相关产品推荐

