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

能否调整TableView和SearchBar的代理方法执行顺序?

解决方案

你遇到的问题本质是系统响应链的执行顺序固定,无法直接修改两个系统代理的回调优先级,可通过以下方案解决:


方案1:延迟执行关闭逻辑(改动最小,推荐)

将searchBarTextDidEndEditing中的关闭table操作异步派发到主队列的下一个执行周期,确保当前runloop中已触发的didSelectRowAt优先执行完成,再执行关闭逻辑。用户不会感知到任何延迟,完全符合业务预期。
修改后的代码如下:

extension CustomSearchBar: UISearchBarDelegate {
    func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
        print("searchBarTextDidEndEditing")            
        self.setShowsCancelButton(false, animated: true)
        // 异步派发到主队列,等待当前所有触摸回调执行完成后再关闭
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            self.closeTableView()
        }
    }
}

方案2:新增状态标识位控制

新增属性标记用户是否正在点击下拉建议列表,仅当用户没有点击列表时才在失焦时关闭table。

实现步骤:

  • 新增状态属性
private var isTappingSuggestionTable: Bool = false
  • 监听table的触摸事件修改状态
// 可以给tableView添加手势识别,或者重写cell的触摸回调
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    let tablePoint = self.convert(point, to: self.tableView)
    if self.tableView.bounds.contains(tablePoint) {
        isTappingSuggestionTable = true
    }
    return super.hitTest(point, with: event)
}
  • 修改失焦逻辑的判断
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
    print("searchBarTextDidEndEditing")            
    self.setShowsCancelButton(false, animated: true)
    guard !isTappingSuggestionTable else {
        isTappingSuggestionTable = false
        return
    }
    self.closeTableView()
}
  • 在didSelectRowAt执行完后重置状态并关闭table。

方案3:失焦时校验点击区域

在searchBarTextDidEndEditing触发时,获取当前用户的点击坐标,转换到当前控件的坐标系内,判断点击位置是否落在下拉table的有效展示区域内,如果是则不执行关闭,否则关闭。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 12:18:03