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

搜索时禁用UIRefreshControl的技术实现问题

解决UISearchController激活时禁用UIRefreshControl的问题

我之前也碰到过一模一样的困扰,试了几个方法后终于搞定了,分享两个亲测有效的方案给你:

方法一:利用UISearchController代理方法

这是最直接的方式,通过监听搜索控制器的显示/隐藏状态,来开关下拉刷新的功能:

  1. 给你的ViewController添加UISearchControllerDelegate协议
  2. 在viewDidLoad里把searchController的代理设为当前控制器
  3. 实现两个代理方法,分别在搜索激活和关闭时控制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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:45:22