搜索时禁用UIRefreshControl的技术实现问题
解决UISearchController激活时禁用UIRefreshControl的问题
我之前也碰到过一模一样的困扰,试了几个方法后终于搞定了,分享两个亲测有效的方案给你:
方法一:利用UISearchController代理方法
这是最直接的方式,通过监听搜索控制器的显示/隐藏状态,来开关下拉刷新的功能:
- 给你的ViewController添加
UISearchControllerDelegate协议 - 在
viewDidLoad里把searchController的代理设为当前控制器 - 实现两个代理方法,分别在搜索激活和关闭时控制refreshControl的状态
class YourViewController: UIViewController, UISearchControllerDelegate, UITableViewDelegate, UITableViewDataSource { // 初始化你的组件 private let tableView = UITableView() private let refreshControl = UIRefreshControl() private let searchController = UISearchController(searchResultsController: nil) override func viewDidLoad() { super.viewDidLoad() // 给tableView添加下拉刷新 tableView.refreshControl = refreshControl refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged) // 配置搜索控制器并设置代理 searchController.delegate = self searchController.searchResultsUpdater = self // 如果需要实时更新搜索结果的话 searchController.obscuresBackgroundDuringPresentation = false // 可选,根据你的UI需求 navigationItem.searchController = searchController // 其他tableView和UI初始化代码... } // 下拉刷新的处理方法 @objc private func handleRefresh() { // 你的刷新逻辑... DispatchQueue.main.asyncAfter(deadline: .now() + 2) { self.refreshControl.endRefreshing() } } // 当搜索控制器激活时禁用下拉刷新 func didPresentSearchController(_ searchController: UISearchController) { refreshControl.isEnabled = false // 额外处理:如果此时正在刷新,直接结束 if refreshControl.isRefreshing { refreshControl.endRefreshing() } } // 当搜索控制器关闭时恢复下拉刷新 func didDismissSearchController(_ searchController: UISearchController) { refreshControl.isEnabled = true } }
方法二:用KVO监听搜索控制器的激活状态
如果代理方法没生效(有时候可能因为导航栏设置或者其他原因),可以用KVO来监听isActive属性的变化:
override func viewDidLoad() { super.viewDidLoad() // 其他初始化代码... // 添加KVO监听isActive属性 searchController.addObserver(self, forKeyPath: "isActive", options: [.new], context: nil) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { guard keyPath == "isActive", let isActive = change?[.newKey] as? Bool else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) return } // 根据激活状态开关下拉刷新 refreshControl.isEnabled = !isActive if isActive && refreshControl.isRefreshing { refreshControl.endRefreshing() } } // 记得在销毁时移除观察者,避免内存泄漏 deinit { searchController.removeObserver(self, forKeyPath: "isActive") }
额外注意点
- 确保你已经把searchController正确赋值给
navigationItem.searchController,否则代理方法可能不会触发 - 如果你的tableView是嵌套在其他scrollView里,可能需要额外处理scrollView的手势冲突,但一般直接控制refreshControl的enabled就足够了
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

