我有一个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:")
可以正常工作。
答案 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