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
相关产品推荐
相关产品推荐

