点击搜索栏后导航栏UIBarButtonItems消失,如何解决该问题?
这个问题我之前做项目的时候也踩过坑——搜东西的时候想点个导航栏按钮还得先取消搜索,体验真的拉胯。下面给你两个实用的解决方案,你可以根据自己的需求选:
方法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
相关产品推荐
相关产品推荐

