zoukankan      html  css  js  c++  java
  • Swift 中 Selector 方法的访问权限控制问题

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

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

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

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

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

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

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

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

    1
    2
    3
    4
    5
    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了。

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

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

  • 相关阅读:
    Sql中CHARINDEX用法
    当没有用 EXISTS 引入子查询时,在选择列表中只能指定一个表达式
    Windows Server 2012 R2安装.NET4.7.2服务问题集合
    详细实例全面解析SQL存储过程
    MySQL 存储过程
    华为远程登陆配置
    数据平台环境部署(mysql、docker、nginx)
    ISIS的路由渗透
    华为模拟器的安装失败(出现40、41、42代码错误,Oracle VM VirtualBox安装出现严重错误以及一直处于开机状态)
    华为模拟器配置动态ospf--虚拟链路、rip重分布、static重分布
  • 原文地址:https://www.cnblogs.com/motoyang/p/4946911.html
Copyright © 2011-2022 走看看