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

设置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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:57:15