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 }
NSNotificationCenter在Swift 4.0 for iOS 11中添加观察者语法
NotificationCenter.default.addObserver(self, selector: #selector(keyboardShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
这是为keyboardWillShow通知名称类型。 其他类型可以从可用选项中选择
选择器的类型是@objc func,它处理键盘显示的方式(这是你的用户功能)