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

Swift4中UITapGestureRecognizer触发带回调Selector函数报错求助

问题原因与解决方案

我之前做底部弹出菜单的时候也踩过一模一样的坑!问题出在手势触发的方法签名和你定义的handleDismiss不匹配,具体来说:

为什么点击遮罩会报错?

你给遮罩绑定的手势是:

blackView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleDismiss)))

iOS中,手势触发的selector方法默认会把触发的手势对象作为参数传递给方法,但你定义的handleDismiss方法参数是一个可选闭包:

@objc func handleDismiss(callback:(() -> ())?) { ... }

系统找不到匹配的方法(它要找带UITapGestureRecognizer参数的方法,或者无参方法),就会抛出unrecognized selector sent to instance的错误。而点击Cancel单元格时是你手动调用带闭包参数的方法,所以完全没问题。

两种解决办法

方法1:重载方法(最推荐)

保留你原来带回调的方法,新增一个供手势调用的无参版本,转调原方法:

// 供手势触发调用的无参版本
@objc func handleDismiss() {
    // 传nil作为回调,不执行额外逻辑
    handleDismiss(callback: nil)
}

// 原来带回调的方法,去掉@objc(因为不需要被系统调用了)
func handleDismiss(callback:(() -> ())?) {
    UIView.animate(withDuration: 0.3, animations: {
        self.blackView.alpha = 0
        //......
    }) { (completed: Bool) in
        callback?()
    }
}

这样手势触发时会调用无参的handleDismiss,再转调带回调的版本,完美兼容两种调用场景。

方法2:修改原方法签名兼容两种场景

直接调整原方法的参数,让它既能接受手势参数,也能接受回调:

@objc func handleDismiss(_ gesture: UITapGestureRecognizer? = nil, callback:(() -> ())? = nil) {
    UIView.animate(withDuration: 0.3, animations: {
        self.blackView.alpha = 0
        //......
    }) { (completed: Bool) in
        callback?()
    }
}

这种方式下,手势触发时会自动传入手势对象(我们用默认值忽略它),点击Cancel单元格时调用:

handleDismiss(callback: { print("callback now") })

也能正常运行,不过可读性不如第一种方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:29:21