如何在Swift中将观察者添加到默认通知中心?我正在尝试移植此行代码,以便在电池电量变化时发送通知。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryLevelChanged:) name:UIDeviceBatteryLevelDidChangeNotification object:nil];
如何在Swift中将观察者添加到默认通知中心?我正在尝试移植此行代码,以便在电池电量变化时发送通知。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryLevelChanged:) name:UIDeviceBatteryLevelDidChangeNotification object:nil];
Answers:
与Objective-C API相同,但是使用Swift的语法。
Swift 4.2和Swift 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
}
UIDeviceBatteryLevelDidChangeNotification
不在引号中?这是一个字符串类型。
@objc
。
发送(发布)通知:
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) {}
发送(发布)通知:
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)
}
发送(发布)通知
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
}
@objc
。
methodOFReceivedNotication
必须使用dynamic
NSObject 注释或为NSObject的子类的成员。
object 0x7fd68852d710 of class 'TestNotifications.MyObject' does not implement methodSignatureForSelector: -- trouble ahead
,Unrecognized selector -[TestNotifications.MyObject methodOFReceivedNotication:]
这样做的一种好方法是使用该addObserver(forName:object:queue:using:)
方法,而不是addObserver(_:selector:name:object:)
使用Objective-C代码中经常使用的方法。第一个变体的优点是您不必@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
表达式。
addObserver(_:selector:name:object:)
与注销方式完全不同。您必须保留返回的对象addObserverForName(_:object:queue:usingBlock:)
并将其传递给removeObserver:
addObserverForName(_:object:queue:usingBlock:)
。
UIViewController
并引用self
它,则需要使用它,[weak self]
否则将有一个参考周期和内存泄漏。
Swift 3.0已将许多“字符串型” API替换为struct
“包装类型”,如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)
现在,所有系统通知类型都被定义为on上的静态常量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)
声明通知名称
extension 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
在块内使用,则需要做一个弱强共舞。更多信息
需要删除基于块的观察者的更多信息
let center = NSNotificationCenter.defaultCenter()
center.removeObserver(self.localeChangeObserver)
使用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)的源传递数据
在Swift 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)
}
}
我能够执行以下操作之一以成功使用选择器- 无需使用@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)
@objc
如果您的观察者类继承自,则无需注释NSObject
。
String
转换Selector
为。:)
@objc
从非NSObject
观察者类的方法中删除了注释,将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)
}
在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在iOS 4.0的Swift 4.0中添加观察者语法
NotificationCenter.default.addObserver(self, selector: #selector(keyboardShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
这是用于keyboardWillShow通知名称类型。可以从可用选项中选择其他类型
选择器的类型为@objc func,用于处理键盘的显示方式(这是您的用户功能)
#selector
必须以注释@objc
。例如:@objc func keyboardShow() { ... }
那让我在Swift 4中呆了一分钟!
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)
}