Swift 中 Selector 方法的访问权限控制问题

28 篇文章 0 订阅

0.jpg

今天用Swift写了个视图,在视图上加个手势,如下所示:

panGestureRecognizer = UIPanGestureRecognizer(target: self, action: "beginDragged:")
addGestureRecognizer(panGestureRecognizer)

运行了下程序,然后崩溃了。崩溃日志如下:

[**.SwipeCardView beginDragged:]: unrecognized selector sent to instance 0x125e5bc10

而我已经在SwipeCardView类中定义了beginDragged:方法,如下所示:

private func beginDragged(gestureRecognizer: UIPanGestureRecognizer) {
  // ....
}

由于我并不想将beginDragged:方法暴露出去,所以将其定义为一个private方法。方法的定义一切正常,手势的Selector方法也设置正常,却报了未找到方法的异常。那问题可能就应该在访问权限问题上了。

我们知道Selector是Objective-C的产物,它用于在运行时作为一个键值去找到对应方法的实现。一个Objective-C的方法是由objc_method结束体定义的,其声明如下:

struct objc_method {
    SEL method_name                    OBJC2_UNAVAILABLE;  // 方法名
    char *method_types                  OBJC2_UNAVAILABLE;
    IMP method_imp                      OBJC2_UNAVAILABLE;  // 方法实现
}

这就要求selector引用的方法必须对ObjC运行时是可见的。而Swift是静态语言,虽然继承自NSObject的类默认对ObjC运行时是可见的,但如果方法是由private关键字修饰的,则方法默认情况下对ObjC运行时并不是可见的,所以就导致了以上的异常:运行时并没找到SwipeCardView类的beginDragged:方法。

所以,我们必须将private修饰的方法暴露给运行时。正确的做法是在 private 前面加上 @objc 关键字,这样就OK了。

@objc private func beginDragged(gestureRecognizer: UIPanGestureRecognizer) {
  // ....
}

另外需要注意的是,如果我们的类是纯Swift类,而不是继承自NSObject,则不管方法是private还是internal或public,如果要用在Selector中,都需要加上@objc修饰符。

参考

  1. SELECTOR

  2. @selector() in Swift?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值