在通知

时间:2017-06-30 02:09:55

标签: ios swift

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

1 个答案:

答案 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使用的“消息传递”接口的一部分。