设置inputAccessoryView后toolbarItems在键盘操作后不显示问题求助
解决UIToolbarItems在键盘显示时消失的问题
这个问题我做项目时也踩过一模一样的坑,核心原因是UIBarButtonItem不能同时属于两个不同的UIToolbar——你直接把视图控制器的toolbarItems赋值给键盘工具栏的items,会导致这些item被自动从原工具栏中移除,而键盘工具栏的渲染时机刚好和这个移除动作冲突,就出现了item消失的情况。虽然你打印toolbarItems的计数还在,但这些item的父容器已经变了,原工具栏自然没法显示它们。
下面给你几个可行的解决方案:
1. 重新创建Toolbar Items(推荐)
不要复用原有的toolbarItems,而是写一个统一的方法来生成工具栏项,原工具栏和键盘工具栏都调用这个方法创建独立的item实例:
// 封装创建工具栏项的方法 private func generateToolbarItems() -> [UIBarButtonItem] { // 根据你的需求创建item,示例如下: let doneBtn = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(onDoneTapped)) let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let customBtn = UIBarButtonItem(title: "自定义操作", style: .plain, target: self, action: #selector(onCustomTapped)) return [flexibleSpace, doneBtn, customBtn] } // 视图加载时初始化原工具栏 override func viewDidLoad() { super.viewDidLoad() toolbarItems = generateToolbarItems() } // 编辑时给键盘设置独立的工具栏项 func textViewShouldBeginEditing(_ textView: UITextView) -> Bool { let keyboardToolbar = UIToolbar() keyboardToolbar.sizeToFit() // 使用新创建的items,避免复用冲突 keyboardToolbar.items = generateToolbarItems() textView.inputAccessoryView = keyboardToolbar return true } // 对应的点击事件 @objc private func onDoneTapped() { view.endEditing(true) } @objc private func onCustomTapped() { // 执行你的自定义操作 }
2. 复制原有的Toolbar Items
如果你的工具栏项比较复杂,不想重新创建,可以复制原item的实例(系统自带的UIBarButtonItem支持直接copy,自定义的item需要实现NSCopying协议):
func textViewShouldBeginEditing(_ textView: UITextView) -> Bool { let keyboardToolbar = UIToolbar() keyboardToolbar.sizeToFit() guard let originalItems = toolbarItems else { return true } // 复制每个item,生成独立实例 let copiedItems = originalItems.map { $0.copy() as! UIBarButtonItem } keyboardToolbar.items = copiedItems textView.inputAccessoryView = keyboardToolbar return true }
3. 提前创建键盘工具栏(优化性能)
如果不需要每次编辑都重新创建工具栏,可以提前在viewDidLoad里初始化好键盘工具栏,后续直接复用:
// 懒加载创建键盘工具栏 private lazy var keyboardToolbar: UIToolbar = { let toolbar = UIToolbar() toolbar.sizeToFit() toolbar.items = generateToolbarItems() return toolbar }() override func viewDidLoad() { super.viewDidLoad() toolbarItems = generateToolbarItems() // 提前给textView设置inputAccessoryView textView.inputAccessoryView = keyboardToolbar } // 此时这个方法里只需要返回true即可 func textViewShouldBeginEditing(_ textView: UITextView) -> Bool { return true }
这样处理后,原工具栏和键盘工具栏的item是完全独立的实例,不会出现视图层级冲突的问题,就能保证两边的工具栏项都正常显示了。
内容的提问来源于stack exchange,提问作者jc127
相关产品推荐
相关产品推荐

