Swift希望#selector的参数暴露给Objective-C

Jas*_*son 25 xcode objective-c ios swift

我有一个Swift项目,我想在UIButton的tap事件中附加一个方法.我有以下代码:

class MyClass {
  let myButton = UIButton(frame: CGRectMake(50, 50, 100, 50))
  init() {
    myButton.addTarget(self, #selector(self.didTap(_:)), forControlEvents: .TouchUpInside)
  }

  func didTap(sender: UIButton) {
    print("Tapped")
  }
}
Run Code Online (Sandbox Code Playgroud)

XCode突出了我的addTarget界限并说:

Argument of '#selector' refers to a method that is not exposed to Objective-C
Run Code Online (Sandbox Code Playgroud)

如果我添加@objc前缀到我func didTap喜欢它建议然后一切正常.

我的构建设置中是否启用了某些导致此奇怪行为的内容?

PS.我在7.3.1中得到了这种行为.但是,如果我在7.2.1中尝试这个,它不接受#selector(method(_:))语法,并且Selector("method:")工作正常.

Dar*_*ren 60

选择器是Objective-C的一个特性,只能与暴露于动态Obj-C运行时的方法一起使用.您不能拥有纯Swift方法的选择器.

如果您的类继承自NSObject那时,它的公共方法会自动暴露给Obj-C.由于您的类不继承,NSObject您必须使用该@objc属性来指示您希望将此方法暴露给Obj-C,以便可以使用Obj-C选择器调用它.

#selector()是Swift 2.2中的新语法.它允许编译器检查您尝试使用的选择器是否确实存在.旧语法已弃用,将在Swift 3.0中删除.


mat*_*att 12

如果我didTap像我建议的那样将@objc前缀添加到我的func中,那么一切正常.

我的构建设置中是否启用了某些导致此奇怪行为的内容?

不,你看到的是正常的.选择器是Objective-C功能,因此使用选择器将消息发送到类实例.Objective-C发送该消息的唯一方法是它是否可以看到您的类或方法本身.MyClass本身不是从NSObject派生的,所以Objective-C看不到它.因此,如果您不想从NSObject派生它,您至少必须通过标记它来将方法暴露给Objective-C @objc.

和选择器("方法:")工作正常

在早期版本的Swift中,编译器在这种情况下无法帮助您,因此您的代码将被编译.但是当消息到达并且Objective-C找不到该方法时,你会崩溃.在整点#selector语法是帮助您避免崩溃.这就是它的作用!