Swift自定义UIButton报unrecognized selector错误如何优化?
崩溃原因
你当前的代码在调用addTarget时,将外部传入的target作为响应选择器的对象,但#selector(tapAction(_:))是定义在BaseButton内部的私有方法,外部target(报错里的UIView实例)不存在该方法,因此触发了无法识别选择器的崩溃。你不需要将target作为参数传入,响应点击的主体本身就是按钮实例。
现有代码修复方案
修改BaseButton的tapInside方法,移除不必要的target参数,将addTarget的响应对象固定为self:
class BaseButton: UIButton { private var action: ((UIButton)->())? // 移除target参数 public func tapInside(action: ((UIButton)->())?) { self.action = action // 响应点击的是按钮自身,所以target填self self.addTarget(self, action: #selector(tapAction(_:)), for: .touchUpInside) } @objc private func tapAction(_ sender: UIButton) { action?(self) } }
调用示例:
let testBtn = BaseButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50)) testBtn.tapInside { [weak self] sender in // 处理点击逻辑 }
无需自定义子类的通用实现
如果不想继承BaseButton,可以通过Swift关联对象给系统UIButton扩展点击闭包能力,全项目的UIButton都可以直接使用:
import UIKit // 关联对象的唯一key private var UIButtonTapActionKey: UInt8 = 0 extension UIButton { // 用关联对象存储点击闭包 private var tapAction: ((UIButton) -> Void)? { get { objc_getAssociatedObject(self, &UIButtonTapActionKey) as? (UIButton) -> Void } set { objc_setAssociatedObject(self, &UIButtonTapActionKey, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC) } } // 对外暴露的添加点击事件方法 func addTapAction(_ action: @escaping (UIButton) -> Void) { self.tapAction = action addTarget(self, action: #selector(internalHandleTap(_:)), for: .touchUpInside) } // 内部私有响应方法 @objc private func internalHandleTap(_ sender: UIButton) { tapAction?(sender) } }
调用示例:
let systemBtn = UIButton(type: .system) systemBtn.addTapAction { [weak self] sender in // 处理点击逻辑 }
注意事项
- 闭包内引用外部对象时必须添加
[weak self]标记,避免循环引用导致内存泄漏 - 重复调用添加点击的方法会覆盖之前设置的闭包,如果需要添加多个点击回调请使用系统原生的
addTarget方法
内容的提问来源于stack exchange,提问作者hanabi_noir
相关产品推荐
相关产品推荐

