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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 14:36:03