在Swift 3中,要注册通知,我可以采取以下方式:
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.n1(notification:)), name: Notification.Name("123"), object: nil)
func n1(notification: Notification){
print("123")
}
// #selector is more brief
NotificationCenter.default.addObserver(self, selector: #selector(n2), name: Notification.Name("456"), object: nil)
func n2(notification: Notification){
print("456")
}
但是,在Xcode 9.0 beta 2(Swift 4.0)中,当我以这种方式注册通知时,对象方法应该有一个前缀@objc
,为什么?使用通知的最佳做法是什么?
Argument of '#selector' refers to instance method 'n1(notification:)' that is not exposed to Objective-C
//Add '@objc' to expose this instance method to Objective-C
@objc func n1(notification: Notification){
print("123")
}
@objc func n2(notification: Notification){
print("456")
}
答案 0 :(得分:4)
你没错。
事实上,苹果公司解释说你应该在Swift 4中使用选择器:
在Objective-C中,选择器是一个引用名称的类型 Objective-C方法。在Swift中,Objective-C选择器由 Selector结构,可以使用#selector构造 表达。为可以从中调用的方法创建选择器 Objective-C,传递方法的名称,例如#selector(MyViewController.tappedButton(sender :))。要为属性的Objective-C getter或setter方法构造选择器,请传递 属性名称以getter:或setter:标签作为前缀,例如#selector(getter:MyViewController.myButton)。
文档链接here。
要回答你关于原因的问题,选择器实际上是一种在可可类之间发送消息的方法,而不是一个快速的功能。所以他们实际上是基于Objective-C,因此你需要保持它们之间的兼容性。
<强>选择器:强>
选择器是用于选择要执行的方法的名称 对象,或替换名称时的唯一标识符 源代码已编译。选择器本身不做任何事情。它 只需识别一种方法。唯一能使选择器出现的东西 与普通字符串不同的方法名称是编译器生成的 确保选择器是唯一的。选择器的用处是什么 (与运行时一起)它就像一个动态函数 指针,对于给定的名称,自动指向 实现适合于使用它的任何类的方法 用。
您可以阅读有关选择器here的更多信息。
但基本上,它们只是cocoa使用的“消息传递”接口的一部分。