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

时间:2016-05-01 03:50:58

标签: ios objective-c xcode swift

我有一个Swift项目,我希望将方法附加到UIButton的点击事件。我有以下代码:

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")
  }
}

XCode突出显示我的addTarget行并说:

Argument of '#selector' refers to a method that is not exposed to Objective-C

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

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

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

3 个答案:

答案 0 :(得分:60)

选择器是Objective-C的一项功能,只能与暴露于动态Obj-C运行时的方法一起使用。你不能拥有一个纯粹的Swift方法的选择器。

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

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

答案 1 :(得分:12)

  

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

     

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

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

  

和Selector(“method:”)工作正常

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

答案 2 :(得分:-2)

您必须从NSObject

继承