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

点击搜索栏后导航栏UIBarButtonItems消失,如何解决该问题?

解决导航栏搜索激活时UIBarButtonItem被隐藏的问题

这个问题我之前做项目的时候也踩过坑——搜东西的时候想点个导航栏按钮还得先取消搜索,体验真的拉胯。下面给你两个实用的解决方案,你可以根据自己的需求选:

方法1:将UISearchBar设为导航栏TitleView(简单直接)

系统默认用navigationItem.searchController绑定搜索控制器时,会在搜索激活时自动替换导航栏的左右按钮。如果你不需要UISearchController的高级功能(比如独立的搜索结果控制器),可以直接把搜索栏作为导航栏的titleView,这样搜索激活时导航栏按钮完全不受影响。

代码示例:

class YourViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 创建并配置搜索栏
        let searchBar = UISearchBar()
        searchBar.placeholder = "搜索..."
        searchBar.delegate = self // 绑定代理处理搜索逻辑
        
        // 把搜索栏设为导航栏标题视图
        navigationItem.titleView = searchBar
        
        // 添加你的自定义按钮
        let button1 = UIBarButtonItem(title: "按钮1", style: .plain, target: self, action: #selector(button1Tapped))
        let button2 = UIBarButtonItem(title: "按钮2", style: .plain, target: self, action: #selector(button2Tapped))
        navigationItem.rightBarButtonItems = [button1, button2]
    }
    
    // MARK: - 按钮点击事件
    @objc private func button1Tapped() {
        // 处理按钮1逻辑
    }
    
    @objc private func button2Tapped() {
        // 处理按钮2逻辑
    }
}

// MARK: - UISearchBarDelegate
extension YourViewController: UISearchBarDelegate {
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        // 在这里处理搜索文本变化,过滤tableView数据
    }
    
    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searchBar.resignFirstResponder()
        // 恢复tableView初始状态
    }
}

优缺点:

  • ✅ 优点:实现简单,无需处理复杂的代理逻辑,按钮始终可见
  • ❌ 缺点:需要手动处理搜索逻辑(比如过滤数据、键盘收起),无法直接使用UISearchController的内置搜索结果管理功能

方法2:用UISearchController代理手动维护按钮(保留搜索控制器功能)

如果你需要UISearchController的便利功能(比如自动管理搜索结果控制器、搜索状态),可以通过代理方法手动控制导航栏按钮的显示,避免系统自动隐藏它们。

代码示例:

class YourViewController: UIViewController {
    private let searchController = UISearchController(searchResultsController: nil)
    private var originalRightButtons: [UIBarButtonItem]? // 保存原来的右按钮
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 配置搜索控制器
        searchController.searchBar.placeholder = "搜索..."
        searchController.obscuresBackgroundDuringPresentation = false // 避免模糊背景
        searchController.searchResultsUpdater = self // 绑定搜索结果更新代理
        searchController.delegate = self // 绑定搜索控制器代理
        
        // 绑定搜索控制器到导航栏
        navigationItem.searchController = searchController
        
        // 添加你的自定义按钮
        let button1 = UIBarButtonItem(title: "按钮1", style: .plain, target: self, action: #selector(button1Tapped))
        let button2 = UIBarButtonItem(title: "按钮2", style: .plain, target: self, action: #selector(button2Tapped))
        navigationItem.rightBarButtonItems = [button1, button2]
    }
    
    // MARK: - 按钮点击事件
    @objc private func button1Tapped() {
        // 处理按钮1逻辑,即使在搜索状态下也能正常触发
    }
    
    @objc private func button2Tapped() {
        // 处理按钮2逻辑
    }
    
    // MARK: - 手动关闭搜索
    @objc private func dismissSearch() {
        searchController.searchBar.resignFirstResponder()
        searchController.dismiss(animated: true)
    }
}

// MARK: - UISearchControllerDelegate
extension YourViewController: UISearchControllerDelegate {
    func willPresentSearchController(_ searchController: UISearchController) {
        // 保存原来的右按钮
        originalRightButtons = navigationItem.rightBarButtonItems
        
        // 创建自定义取消按钮
        let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(dismissSearch))
        
        // 把原来的按钮和取消按钮一起放回导航栏
        if let originalButtons = originalRightButtons {
            navigationItem.rightBarButtonItems = originalButtons + [cancelButton]
        }
    }
    
    func willDismissSearchController(_ searchController: UISearchController) {
        // 恢复原来的右按钮
        navigationItem.rightBarButtonItems = originalRightButtons
    }
}

// MARK: - UISearchResultsUpdating
extension YourViewController: UISearchResultsUpdating {
    func updateSearchResults(for searchController: UISearchController) {
        // 在这里处理搜索结果更新
        if let searchText = searchController.searchBar.text {
            // 过滤tableView数据
        }
    }
}

优缺点:

  • ✅ 优点:保留UISearchController的所有内置功能,搜索状态下按钮依然可用
  • ❌ 缺点:需要额外处理按钮的保存和恢复逻辑,注意避免布局冲突(比如按钮过多导致导航栏拥挤)

我个人更推荐第二种方法,因为它能兼顾搜索功能的完整性和按钮的可访问性。如果你的按钮比较多,可以调整按钮的样式(比如用图标按钮代替文字按钮)来避免导航栏拥挤。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:54:53