Swift UIKit纯代码实现UISearchController右侧添加按钮
纯代码实现导航栏UISearchController右侧添加自定义按钮
以下方案适配iOS 13+版本,全程纯代码实现,无storyboard/xib依赖,不会出现搜索激活时按钮被遮挡、布局错乱问题。
核心实现思路
- 用iOS 11之后系统提供的
navigationItem.searchController挂载搜索控制器,不要手动把searchBar塞到tableView头部或者导航栏titleView,避免系统布局适配问题 - 隐藏UISearchBar自带的系统取消按钮,空出右侧导航栏位置放自定义按钮
- 监听搜索控制器的激活/退出回调,在状态切换时重新挂载自定义按钮,避免系统在搜索态重置导航栏配置导致按钮消失
以下代码以Swift为例,Objective-C开发逻辑完全一致,仅语法写法有区别,核心配置项、代理回调逻辑通用。
核心代码实现
1. 控制器基础定义
import UIKit class YourViewController: UIViewController, UISearchControllerDelegate { // 初始化搜索控制器,传nil代表搜索结果在当前页展示 private let searchController = UISearchController(searchResultsController: nil) // 自定义右侧按钮 private lazy var customRightBarBtn: UIBarButtonItem = { let btn = UIBarButtonItem( title: "取消", style: .plain, target: self, action: #selector(rightBarBtnAction) ) btn.tintColor = .systemBlue return btn }() override func viewDidLoad() { super.viewDidLoad() setupSearchController() } }
2. 搜索控制器基础配置
private func setupSearchController() { // 搜索时不蒙层当前页面 searchController.obscuresBackgroundDuringPresentation = false searchController.searchBar.placeholder = "搜索内容" // 隐藏系统自带取消按钮,给自定义按钮腾位置 searchController.searchBar.showsCancelButton = false // 绑定搜索代理 searchController.delegate = self // 把搜索控制器挂到导航项上 navigationItem.searchController = searchController // 滚动时不隐藏搜索栏,可根据自己业务需求开关 navigationItem.hidesSearchBarWhenScrolling = false // 初始状态设置右侧按钮 navigationItem.rightBarButtonItem = customRightBarBtn definesPresentationContext = true }
3. 搜索状态切换时的按钮适配
// MARK: - UISearchControllerDelegate func willPresentSearchController(_ searchController: UISearchController) { // 搜索即将激活时,重新设置右侧按钮,避免被系统配置覆盖 navigationItem.rightBarButtonItem = customRightBarBtn } func willDismissSearchController(_ searchController: UISearchController) { // 搜索即将退出时,重新设置右侧按钮 navigationItem.rightBarButtonItem = customRightBarBtn } // 右侧按钮点击事件 @objc private func rightBarBtnAction() { // 这里写自己的业务逻辑,比如退出搜索、跳转其他页面等 searchController.isActive = false }
常见踩坑提醒
- 不要直接把自定义按钮addSubview到UISearchBar上:跨iOS版本会出现位置偏移、点击区域失效、布局错乱问题
- 不要通过runtime或者遍历子视图修改UISearchBar内部层级:会存在App Store审核风险,且iOS大版本升级后很容易失效
- 如果需要在搜索激活/非激活状态切换按钮样式,直接在
willPresentSearchController和willDismissSearchController回调里修改按钮的title、image属性即可,不需要额外做布局适配
内容的提问来源于stack exchange,提问作者rayan taj
相关产品推荐
相关产品推荐

