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

如何收起UISearchBar键盘且不影响其他功能的正常使用?

问题原因

你给父视图添加的全局UITapGestureRecognizer默认会优先拦截所有点击事件,当你点击UITableViewCell时,事件会被该手势先捕获消费,不会继续向下传递给UITableView的事件处理体系,因此didSelectRowAt方法无法触发。

解决方案

方案1:通过手势代理过滤点击区域(推荐)

让当前控制器遵守UIGestureRecognizerDelegate协议,在代理方法中判断点击区域,如果是落在UITableView范围内就放弃手势响应,把事件交还给UITableView处理。
修改后的完整代码如下:

// 首先遵守UIGestureRecognizerDelegate协议
class YourViewController: UIViewController, UIGestureRecognizerDelegate {

    @IBOutlet weak var searchbar: UISearchBar!
    @IBOutlet weak var yourTableView: UITableView! // 替换为你自己的tableView变量名

    override func viewDidLoad() {
        super.viewDidLoad()

        let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
        tap.delegate = self // 给手势设置代理
        view.addGestureRecognizer(tap)
    }

    @objc func handleTap() {
        searchbar.resignFirstResponder()
    }

    // 实现手势代理方法,过滤不需要响应手势的区域
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        // 点击区域落在tableView内时,不响应该手势
        if touch.view?.isDescendant(of: yourTableView) == true {
            return false
        }
        return true
    }
}

方案2:设置手势不拦截下层事件

如果不需要精准控制区域,也可以直接修改手势的cancelsTouchesInView属性为false,手势识别后不会截断事件,会继续传递给下层视图,同时实现收起键盘和触发cell点击的效果:

override func viewDidLoad() {
    super.viewDidLoad()

    let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
    tap.cancelsTouchesInView = false // 添加这行配置
    view.addGestureRecognizer(tap)
}

@objc func handleTap() {
    searchbar.resignFirstResponder()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 09:57:05