如何在 Swift 中将观察者添加到默认通知中心?我正在尝试移植这行代码,以在电池电量发生变化时发送通知。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryLevelChanged:) name:UIDeviceBatteryLevelDidChangeNotification object:nil];
斯威夫特 4.0 和 Xcode 9.0+:
发送(发布)通知:
NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil)
或者
NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil, userInfo: ["Renish":"Dadhaniya"])
接收(获取)通知:
NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)
收到通知的函数方法处理程序:
@objc func methodOfReceivedNotification(notification: Notification) {}
斯威夫特 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)
}
斯威夫特 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
}
它与 Objective-C API 相同,但使用 Swift 的语法。
斯威夫特 4.2 和斯威夫特 5:
NotificationCenter.default.addObserver(
self,
selector: #selector(self.batteryLevelChanged),
name: UIDevice.batteryLevelDidChangeNotification,
object: nil)
如果你的观察者不是继承自一个 Objective-C 对象,你必须在你的方法前面加上 @objc
才能将它用作选择器。
@objc private func batteryLevelChanged(notification: NSNotification){
//do stuff using the userInfo property of the notification object
}
参见NSNotificationCenter Class Reference、Interacting with Objective-C APIs
UIDeviceBatteryLevelDidChangeNotification
不在引号中?它是一个字符串类型。
@objc
注释类或目标方法。
一个很好的方法是使用 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
expressions。
addObserver(_:selector:name:object:)
的注销方式完全不同。您必须保留 addObserverForName(_:object:queue:usingBlock:)
返回的对象并将其传递给 removeObserver:
addObserverForName(_:object:queue:usingBlock:)
返回的对象。
UIViewController
中使用它并在该闭包中引用 self
,则需要使用 [weak self]
否则您将遇到引用循环和内存泄漏。
声明一个通知名称扩展 Notification.Name { static let purchaseDidFinish = Notification.Name("purchaseDidFinish") } 您可以通过两种方式添加观察者: 使用 Selector NotificationCenter.default.addObserver(self, selector: #selector(myFunction), name: .purchaseDidFinish, object: nil) @objc func myFunction(notification: Notification) { print(notification.object ?? "") //myObject print(notification.userInfo ?? "") //[AnyHashable("key"): "Value"] } 或使用 block NotificationCenter.default.addObserver(forName: .purchaseDidFinish, object: nil, queue: nil) { [weak self] (notification) in guard let strongSelf = self else { return } strongSelf.myFunction(notification : notification) } func myFunction(notification: Notification) { print(notification.object ?? "") //myObject print(notification.userInfo ?? "") //[AnyHashable("key"): "Value"] }发布您的通知 NotificationCenter.default.post(name: .purchaseDidFinish, object: "myObject", userInfo: ["key": "Value"])
从 iOS 9 和 OS X 10.11 开始。 NSNotificationCenter 观察者在被释放时不再需要注销自己。更多信息
对于基于 block
的实现,如果您想在块内使用 self
,则需要进行弱强舞蹈。 more info
需要移除基于块的观察者more info
let center = NSNotificationCenter.defaultCenter()
center.removeObserver(self.localeChangeObserver)
Xcode 8 中的 Swift 3.0
Swift 3.0 已经用 struct
个“包装器类型”替换了许多“字符串类型”API,NotificationCenter 就是这种情况。通知现在由 struct Notfication.Name
而不是 String
标识。请参阅 Migrating to Swift 3 guide。
以前的用法:
// 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)
使用 NSNotificationCenter 传递数据
您还可以使用 swift 3.0 中的 NotificationCentre 和 swift 2.0 中的 NSNotificationCenter 传递数据。
斯威夫特 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
}
}
斯威夫特 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
}
}
来源pass data using NotificationCentre(swift 3.0) and NSNotificationCenter(swift 2.0)
在斯威夫特 5
假设如果想从 ViewControllerB 接收数据到 ViewControllerA
ViewControllerA(接收器)
import UIKit
class ViewControllerA: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//MARK: - - - - - Code for Passing Data through Notification Observer - - - - -
// add observer in controller(s) where you want to receive data
NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)
}
//MARK: - - - - - Method for receiving Data through Post Notificaiton - - - - -
@objc func methodOfReceivedNotification(notification: Notification) {
print("Value of notification : ", notification.object ?? "")
}
}
ViewControllerB(发件人)
import UIKit
class ViewControllerB: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//MARK: - - - - - Set data for Passing Data Post Notification - - - - -
let objToBeSent = "Test Message from Notification"
NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: objToBeSent)
}
}
Swift 5 通知观察者
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(batteryLevelChanged), name: UIDevice.batteryLevelDidChangeNotification, object: nil)
}
@objc func batteryLevelChanged(notification : NSNotification){
//do here code
}
override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(self, name: UIDevice.batteryLevelDidChangeNotification, object: nil)
}
我可以执行以下操作之一来成功使用选择器 - 无需使用 @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)
NSObject
,则无需使用 @objc
进行注释。
String
显式转换为 Selector
。 :)
NSObject
观察者类的方法中删除了 @objc
注释,将 as Selector
转换添加到 String
选择器名称,当通知触发时应用程序崩溃。我的 Swift 版本和你的完全一样。
@objc
注释对您有用,而这种方式不起作用,那么继续注释!
在 swift 2.2 - XCode 7.3 中,我们将 #selector
用于 NSNotificationCenter
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(rotate), name: UIDeviceOrientationDidChangeNotification, object: nil)
我们也应该删除通知。
前任。
deinit
{
NotificationCenter.default.removeObserver(self, name:NSNotification.Name(rawValue: "notify"), object: nil)
}
这是自定义通知观察者和发布的非常简单的示例
添加通知观察者
NotificationCenter.default.addObserver(self, selector: #selector(myFunction), name: Notification.Name("CustomeNotificationName"), object: nil)
添加 Selector 并处理 Observer 调用
@objc func myFunction(notification: Notification) {
//Write you code
}
需要时发布通知(观察者)。
NotificationCenter.default.post(name: NSNotification.Name("CustomeNotificationName"), object: "Object", userInfo: ["key":"Value"])
注意:- 离开屏幕时创建用户,您需要删除观察者。例如
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self);
}
在 swift 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 通知名称类型。可以从可用选项中选择其他类型
Selector 是 @objc func 类型,它处理键盘的显示方式(这是您的用户函数)
#selector
关联的函数必须用 @objc
注释。例如:@objc func keyboardShow() { ... }
这让我在 Swift 4 中呆了一分钟!
斯威夫特 5 和 Xcode 10.2:
NotificationCenter.default.addObserver(
self,
selector: #selector(batteryLevelDidChangeNotification),
name: UIDevice.batteryLevelDidChangeNotification,
object: nil)
@objc
注释类或目标方法。methodOFReceivedNotication
必须用dynamic
注释或者是 NSObject 子类的成员。object 0x7fd68852d710 of class 'TestNotifications.MyObject' does not implement methodSignatureForSelector: -- trouble ahead
、Unrecognized selector -[TestNotifications.MyObject methodOFReceivedNotication:]