Swift开发如何通过UIView扩展为视图添加点击响应动作?
错误原因
你扩展中的实现是把手势识别器的target设置为了UIView实例自身,而你传入的#selector(hello)是定义在ViewController中的方法,触发手势时系统会去UIView类中查找hello方法,找不到就会抛出未识别selector的异常。而你写的setAction方法里手势target是self也就是当前ViewController实例,和selector所属的类匹配,所以运行正常。
方案1:传入target参数(兼容现有selector写法)
修改UIView扩展,增加target参数指定selector所属的响应对象:
extension UIView { public func addTapAction(target: Any, action: Selector) { isUserInteractionEnabled = true let gesture = UITapGestureRecognizer(target: target, action: action) addGestureRecognizer(gesture) } }
调用方式:
menu.addTapAction(target: self, action: #selector(hello))
方案2:闭包回调实现(高频使用更便捷)
这种方案不用每次单独写selector对应的方法,使用更简洁,需要用Runtime关联对象存储回调:
import UIKit private var tapActionKey: UInt8 = 0 extension UIView { typealias TapAction = () -> Void private var tapAction: TapAction? { get { objc_getAssociatedObject(self, &tapActionKey) as? TapAction } set { objc_setAssociatedObject(self, &tapActionKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } public func addTapAction(_ action: @escaping TapAction) { isUserInteractionEnabled = true tapAction = action let gesture = UITapGestureRecognizer(target: self, action: #selector(triggerTapAction)) addGestureRecognizer(gesture) } @objc private func triggerTapAction() { tapAction?() } }
调用方式:
menu.addTapAction { print("Hello") } // 无需额外声明@objc的hello方法
注意:如果闭包内需要引用当前ViewController,记得用
[weak self]避免循环引用:menu.addTapAction { [weak self] in self?.doSomething() }
内容的提问来源于stack exchange,提问作者Punreach Rany
相关产品推荐
相关产品推荐

