NSNotificationCenter addObserver在Swift中

你如何将Swift中的观察者添加到默认通知中心? 我试图移植这个代码,当电池电量发生变化时发送通知。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryLevelChanged:) name:UIDeviceBatteryLevelDidChangeNotification object:nil]; 

它与Objective-C API相同,但使用Swift的语法。

 NSNotificationCenter.defaultCenter().addObserver( self, selector: #selector(batteryLevelChanged), name: UIDeviceBatteryLevelDidChangeNotification, object: nil) 

或者在Swift 3中:

 NotificationCenter.default.addObserver( self, selector: #selector(self.batteryLevelChanged), name: .UIDeviceBatteryLevelDidChange, object: nil) 

如果您的观察者不从Objective-C对象继承,则必须在@objc前缀以将其用作选择器。

 @objc func batteryLevelChanged(notification: NSNotification){ //do stuff } 

请参阅NSNotificationCenter类参考 , 与Objective-C API进行交互

Swift 3.0&Xcode 8.0+:

发送(发布)通知:

 NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil) 

接收(获取)通知:

 NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil) 

接收通知的方法处理程序:

 func methodOfReceivedNotification(notification: Notification){ //Take Action on Notification } 

删除通知:

 deinit { NotificationCenter.default.removeObserver(self, name: Notification.Name("NotificationIdentifier"), object: nil) } 

Swift 2.3&Xcode 7:

发送(发布)通知

  NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil) 

接收(获取)通知

  NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(_:)), name:"NotificationIdentifier", object: nil) 

接收通知的方法处理程序

 func methodOfReceivedNotification(notification: NSNotification){ //Take Action on Notification } 


对于历史上的Xcode版本…



发送(发布)通知

 NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil) 

接收(获取)通知

 NSNotificationCenter.defaultCenter().addObserver(self, selector: "methodOfReceivedNotification:", name:"NotificationIdentifier", object: nil) 

删除通知

 NSNotificationCenter.defaultCenter().removeObserver(self, name: "NotificationIdentifier", object: nil) NSNotificationCenter.defaultCenter().removeObserver(self) // Remove from all notifications being observed 

接收通知的方法处理程序

 func methodOfReceivedNotification(notification: NSNotification){ //Take Action on Notification } 

使用@objc注释类或目标方法

 @objc private func methodOfReceivedNotification(notification: NSNotification){ //Take Action on Notification } //Or dynamic private func methodOfReceivedNotification(notification: NSNotification){ //Take Action on Notification } 

Xcode 8中的Swift 3.0

Swift 3.0用struct “包装器类型”代替了许多“字符串型”的API,就像NotificationCenter一样。 通知现在由一个struct Notfication.Name而不是String标识。 请参阅迁移到Swift 3指南 。

以前用法:

 // Define identifier let notificationIdentifier: String = "NotificationIdentifier" // Register to receive notification NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(_:)), name: notificationIdentifier, object: nil) // Post a notification NSNotificationCenter.defaultCenter().postNotificationName(notificationIdentifier, object: nil) 

新的Swift 3.0用法:

 // Define identifier let notificationName = Notification.Name("NotificationIdentifier") // Register to receive notification NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification), name: notificationName, object: nil) // Post notification NotificationCenter.default.post(name: notificationName, object: nil) 

现在,所有的系统通知类型都被定义为Notification.Name上的静态常量; 即.UIDeviceBatteryLevelDidChange.UIApplicationDidFinishLaunching.UITextFieldTextDidChange等。

您可以使用自己的自定义通知来扩展Notification.Name ,以便与系统通知保持一致:

 // Definition: extension Notification.Name { static let yourCustomNotificationName = Notification.Name("yourCustomNotificationName") } // Usage: NotificationCenter.default.post(name: .yourCustomNotificationName, object: nil) 

这样做的一个好方法是使用addObserver(forName:object:queue:using:)方法,而不是通常在Objective-C代码中使用的addObserver(_:selector:name:object:)方法。 第一个变体的优点是你不必在你的方法中使用@objc属性:

  func batteryLevelChanged(notification: Notification) { // do something useful with this information } let observer = NotificationCenter.default.addObserver( forName: NSNotification.Name.UIDeviceBatteryLevelDidChange, object: nil, queue: nil, using: batteryLevelChanged) 

你甚至可以使用闭包而不是方法,如果你想:

  let observer = NotificationCenter.default.addObserver( forName: NSNotification.Name.UIDeviceBatteryLevelDidChange, object: nil, queue: nil) { _ in print("🔋") } 

您可以使用返回值来停止稍后通知通知:

  NotificationCenter.default.removeObserver(observer) 

在使用这个方法的时候,还有另一个优点,那就是它不需要你使用选择器字符串,这个选择器字符串不能被编译器静态地检查,所以如果方法被重命名的话就很脆弱,但是Swift 2.2和后来包括解决这个问题的#selector表达式 。

使用NSNotificationCenter传递数据

您也可以使用Swift 3.0中的NotificationCentre和swift 2.0中的NSNotificationCenter传递数据。

Swift 2.0版本

使用userInfo这是一个可选的类型[NSObject:AnyObject]字典的信息?

 let imageDataDict:[String: UIImage] = ["image": image] // Post a notification NSNotificationCenter.defaultCenter().postNotificationName(notificationName, object: nil, userInfo: imageDataDict) // Register to receive notification in your class NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.showSpinningWheel(_:)), name: notificationName, object: nil) // handle notification func showSpinningWheel(notification: NSNotification) { if let image = notification.userInfo?["image"] as? UIImage { // do something with your image } } 

Swift 3.0版本

userInfo现在需要[AnyHashable:Any]? 作为一个参数,我们在Swift中提供了一个字典文字

 let imageDataDict:[String: UIImage] = ["image": image] // post a notification NotificationCenter.default.post(name: NSNotification.Name(rawValue: "notificationName"), object: nil, userInfo: imageDataDict) // `default` is now a property, not a method call // Register to receive notification in your class NotificationCenter.default.addObserver(self, selector: #selector(self.showSpinningWheel(_:)), name: NSNotification.Name(rawValue: "notificationName"), object: nil) // handle notification func showSpinningWheel(_ notification: NSNotification) { if let image = notification.userInfo?["image"] as? UIImage { // do something with your image } } 

源传递数据使用NotificationCentre(swift 3.0)和NSNotificationCenter(swift 2.0)

我可以执行以下操作之一来成功使用选择器 – 无需使用@objc注释任何内容:

 NSNotificationCenter.defaultCenter().addObserver(self, selector:"batteryLevelChanged:" as Selector, name:"UIDeviceBatteryLevelDidChangeNotification", object:nil) 

要么

 let notificationSelector: Selector = "batteryLevelChanged:" NSNotificationCenter.defaultCenter().addObserver(self, selector: notificationSelector, name:"UIDeviceBatteryLevelDidChangeNotification", object:nil) 

我的xcrun版本显示Swift 1.2,这个工作在Xcode 6.4和Xcode 7 beta 2(我认为会使用Swift 2.0):

 $xcrun swift --version Apple Swift version 1.2 (swiftlang-602.0.53.1 clang-602.0.53) 

在swift 2.2 – XCode 7.3中,我们使用NSNotificationCenter #selector

  NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(rotate), name: UIDeviceOrientationDidChangeNotification, object: nil) 

我们也应该删除通知。

防爆。

 deinit { NotificationCenter.default.removeObserver(self, name:NSNotification.Name(rawValue: "notify"), object: nil) } 

在迅速3,Xcode 8.2: – 检查电池状态水平

 //Add observer NotificationCenter.default.addObserver(self, selector: #selector(batteryStateDidChange), name: NSNotification.Name.UIDeviceBatteryStateDidChange, object: nil) //Fired when battery level changes func batteryStateDidChange(notification: NSNotification){ //perform manipulation here } 

NSNotificationCenterSwift 4.0 for iOS 11中添加观察者语法

  NotificationCenter.default.addObserver(self, selector: #selector(keyboardShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil) 

这是为keyboardWillShow通知名称类型。 其他类型可以从可用选项中选择

选择器的类型是@objc func,它处理键盘显示的方式(这是你的用户功能)