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

使用UISearchController时如何让导航栏按钮项始终显示

问题原因

UISearchController 激活时系统会默认接管导航栏展示,自动隐藏原 navigationItem 配置的按钮,仅展示搜索框相关控件,这是导致 Done、Cancel 按钮消失的核心原因。

解决方案

你只需要新增/调整以下两处配置即可让导航按钮始终显示:

  • 首先禁用 UISearchController 对导航栏的默认接管行为,添加代码:
    searchController.hidesNavigationBarDuringPresentation = false
  • 若需要兼容 iOS 15 及更低版本,额外实现 UISearchController 的代理回调,在搜索状态切换时重新赋值导航按钮即可:
// 首先遵循 UISearchControllerDelegate 协议
class TradeSelectionController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate, UISearchControllerDelegate  {
    // ...原有代码
    func searchBarSetup() {
        // ...原有配置
        searchController.delegate = self // 新增代理绑定
        searchController.hidesNavigationBarDuringPresentation = false // 新增这行
    }
    // 新增两个代理方法
    func willPresentSearchController(_ searchController: UISearchController) {
        resetNavigationBarButtons()
    }
    
    func willDismissSearchController(_ searchController: UISearchController) {
        resetNavigationBarButtons()
    }
    
    // 把导航按钮配置抽成公共方法
    private func resetNavigationBarButtons() {
        self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneAction))
        self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelAction))
    }
}
现有代码优化建议
  • 避免使用隐式解包的 searchController : UISearchController!,改为直接初始化常量:let searchController = UISearchController(searchResultsController: nil),降低崩溃风险
  • 当前updateSearchResults方法中,搜索框失活就调用dismiss的逻辑不符合常规交互,用户仅取消搜索时不需要关闭当前页面,建议改为清空搜索关键字、重置列表数据源即可
  • 不需要手动设置searchController.searchBar.showsCancelButton = false,禁用导航栏接管后系统不会自动显示搜索框的取消按钮
完整修改后参考代码
import Foundation
import UIKit
class TradeSelectionController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate, UISearchControllerDelegate  {
    
    let searchController = UISearchController(searchResultsController: nil)
    var isSearching = false
    // 可选:存储搜索关键字用于过滤数据源
    var searchKeyword: String? = nil
    
    override func viewDidLoad() {
        super.viewDidLoad()
        addCancelBarItemWithBackButton(.present)
        setup()
        searchBarSetup()
    }
    
    func searchBarSetup() {
        tableView.allowsMultipleSelection = true
        tableView.estimatedRowHeight = tableView.rowHeight
        tableView.rowHeight = UITableView.automaticDimension
        
        searchController.searchResultsUpdater = self
        searchController.searchBar.delegate = self
        searchController.delegate = self
        searchController.obscuresBackgroundDuringPresentation = false
        searchController.hidesNavigationBarDuringPresentation = false
        searchController.searchBar.autocapitalizationType = .none
        
        navigationItem.searchController = searchController
        navigationItem.hidesSearchBarWhenScrolling = true
        // 初始设置导航按钮
        resetNavigationBarButtons()
    }
 
    private func setup() {
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "TradeSelectionTableViewCell")
        tableView.separatorStyle = .none
    }
    
    private func resetNavigationBarButtons() {
        self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneAction))
        self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelAction))
    }
    
    func updateSearchResults(for searchController: UISearchController) {
        searchKeyword = searchController.searchBar.text
        isSearching = searchController.isActive
        // 这里替换为你自己的数据源过滤逻辑
        tableView.reloadData()
    }
    
    func willPresentSearchController(_ searchController: UISearchController) {
        resetNavigationBarButtons()
    }
    
    func willDismissSearchController(_ searchController: UISearchController) {
        resetNavigationBarButtons()
    }
    
    @objc private func cancelAction(_ sender: Any?) {
        dismiss(animated: true, completion: nil)
    }
    @objc private func doneAction(_ sender: Any?) {
        dismiss(animated: true, completion: nil)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 23:36:09