ios Swift 中的 NSNotificationCenter addObserver
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24049020/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
NSNotificationCenter addObserver in Swift
提问by Berry Blue
How do you add an observer in Swift to the default notification center? I'm trying to port this line of code that sends a notification when the battery level changes.
如何将 Swift 中的观察者添加到默认通知中心?我正在尝试移植这行代码,当电池电量发生变化时发送通知。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryLevelChanged:) name:UIDeviceBatteryLevelDidChangeNotification object:nil];
回答by Renish Dadhaniya
Swift 4.0 & Xcode 9.0+:
Swift 4.0 和 Xcode 9.0+:
Send(Post) Notification:
发送(发布)通知:
NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil)
OR
或者
NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil, userInfo: ["Renish":"Dadhaniya"])
Receive(Get) Notification:
接收(获取)通知:
NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)
Function-Method handler for received Notification:
接收通知的函数方法处理程序:
@objc func methodOfReceivedNotification(notification: Notification) {}
Swift 3.0 & Xcode 8.0+:
Swift 3.0 和 Xcode 8.0+:
Send(Post) Notification:
发送(发布)通知:
NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil)
Receive(Get) Notification:
接收(获取)通知:
NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)
Method handler for received Notification:
接收通知的方法处理程序:
func methodOfReceivedNotification(notification: Notification) {
// Take Action on Notification
}
Remove Notification:
删除通知:
deinit {
NotificationCenter.default.removeObserver(self, name: Notification.Name("NotificationIdentifier"), object: nil)
}
Swift 2.3 & Xcode 7:
斯威夫特 2.3 和 Xcode 7:
Send(Post) Notification
发送(发布)通知
NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)
Receive(Get) Notification
接收(获取)通知
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(_:)), name:"NotificationIdentifier", object: nil)
Method handler for received Notification
接收通知的方法处理程序
func methodOfReceivedNotification(notification: NSNotification){
// Take Action on Notification
}
For historic Xcode versions...
对于历史悠久的 Xcode 版本...
Send(Post) Notification
发送(发布)通知
NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)
Receive(Get) Notification
接收(获取)通知
NSNotificationCenter.defaultCenter().addObserver(self, selector: "methodOfReceivedNotification:", name:"NotificationIdentifier", object: nil)
Remove Notification
删除通知
NSNotificationCenter.defaultCenter().removeObserver(self, name: "NotificationIdentifier", object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self) // Remove from all notifications being observed
Method handler for received Notification
接收通知的方法处理程序
func methodOfReceivedNotification(notification: NSNotification) {
// Take Action on Notification
}
Annotate either the class or the target method with @objc
使用 @objc 注释类或目标方法
@objc private func methodOfReceivedNotification(notification: NSNotification) {
// Take Action on Notification
}
// Or
dynamic private func methodOfReceivedNotification(notification: NSNotification) {
// Take Action on Notification
}
回答by Connor
It's the same as the Objective-C API, but uses Swift's syntax.
它与 Objective-C API 相同,但使用 Swift 的语法。
Swift 4.2 & Swift 5:
斯威夫特 4.2 和斯威夫特 5:
NotificationCenter.default.addObserver(
self,
selector: #selector(self.batteryLevelChanged),
name: UIDevice.batteryLevelDidChangeNotification,
object: nil)
If your observer does not inherit from an Objective-C object, you must prefix your method with @objc
in order to use it as a selector.
如果您的观察者不是从 Objective-C 对象继承的,则您必须为您的方法添加前缀@objc
以将其用作选择器。
@objc private func batteryLevelChanged(notification: NSNotification){
//do stuff using the userInfo property of the notification object
}
See NSNotificationCenter Class Reference, Interacting with Objective-C APIs
回答by Jon Colverson
A nice way of doing this is to use the addObserver(forName:object:queue:using:)
method rather than the addObserver(_:selector:name:object:)
method that is often used from Objective-C code. The advantage of the first variant is that you don't have to use the @objc
attribute on your method:
这样做的一个好方法是使用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)
and you can even just use a closure instead of a method if you want:
如果需要,您甚至可以只使用闭包而不是方法:
let observer = NotificationCenter.default.addObserver(
forName: NSNotification.Name.UIDeviceBatteryLevelDidChange,
object: nil, queue: nil) { _ in print("") }
You can use the returned value to stop listening for the notification later:
您可以使用返回值稍后停止监听通知:
NotificationCenter.default.removeObserver(observer)
There used to be another advantage in using this method, which was that it doesn't require you to use selector strings which couldn't be statically checked by the compiler and so were fragile to breaking if the method is renamed, but Swift 2.2 and later include #selector
expressionsthat fix that problem.
过去使用这种方法还有另一个优势,那就是它不需要你使用编译器无法静态检查的选择器字符串,因此如果重命名方法,很容易被破坏,但是 Swift 2.2 和稍后包含解决该问题的#selector
表达式。
回答by Jeffrey Fulton
Swift 3.0 in Xcode 8
Xcode 8 中的 Swift 3.0
Swift 3.0 has replaced many "stringly-typed" APIs with struct
"wrapper types", as is the case with NotificationCenter. Notifications are now identified by a struct Notfication.Name
rather than by String
. See the Migrating to Swift 3 guide.
Swift 3.0 已经用struct
“包装器类型”替换了许多“字符串类型”的 API ,就像 NotificationCenter 的情况一样。通知现在由 标识struct Notfication.Name
而不是由标识String
。请参阅迁移到 Swift 3 指南。
Previoususage:
以前的用法:
// 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)
New Swift 3.0 usage:
新的 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)
All of the system notification types are now defined as static constants on Notification.Name
; i.e. .UIDeviceBatteryLevelDidChange
, .UIApplicationDidFinishLaunching
, .UITextFieldTextDidChange
, etc.
所有系统通知类型现在都定义为静态常量Notification.Name
;即.UIDeviceBatteryLevelDidChange
,.UIApplicationDidFinishLaunching
,.UITextFieldTextDidChange
等等。
You can extend Notification.Name
with your own custom notifications in order to stay consistent with the system notifications:
您可以Notification.Name
使用自己的自定义通知进行扩展,以与系统通知保持一致:
// Definition:
extension Notification.Name {
static let yourCustomNotificationName = Notification.Name("yourCustomNotificationName")
}
// Usage:
NotificationCenter.default.post(name: .yourCustomNotificationName, object: nil)
回答by Warif Akhand Rishi
Declare a notification name
extension Notification.Name { static let purchaseDidFinish = Notification.Name("purchaseDidFinish") }
You can add observer in two ways:
Using
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"] }
or using
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"] }
Post your notification
NotificationCenter.default.post(name: .purchaseDidFinish, object: "myObject", userInfo: ["key": "Value"])
声明一个通知名称
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"])
from iOS 9 and OS X 10.11. It is no longer necessary for an NSNotificationCenter observer to un-register itself when being deallocated. more info
从 iOS 9 和 OS X 10.11。NSNotificationCenter 观察者在被释放时不再需要取消注册自己。更多信息
For a block
based implementation you need to do a weak-strong dance if you want to use self
inside the block. more info
对于block
基于实现的实现,如果您想self
在块内使用,则需要进行弱-强舞蹈。更多信息
Block based observers need to be removed more info
需要删除基于块的观察者更多信息
let center = NSNotificationCenter.defaultCenter()
center.removeObserver(self.localeChangeObserver)
回答by Sahil
Pass Data using NSNotificationCenter
使用 NSNotificationCenter 传递数据
You can also pass data using NotificationCentre in swift 3.0 and NSNotificationCenter in swift 2.0.
您还可以使用 swift 3.0 中的 NotificationCentre 和 swift 2.0 中的 NSNotificationCenter 传递数据。
Swift 2.0 Version
斯威夫特 2.0 版本
Pass info using userInfo which is a optional Dictionary of type [NSObject : AnyObject]?
使用 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 Version
斯威夫特 3.0 版本
The userInfo now takes [AnyHashable:Any]? as an argument, which we provide as a dictionary literal in Swift
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
}
}
Source pass data using NotificationCentre(swift 3.0) and NSNotificationCenter(swift 2.0)
使用 NotificationCentre(swift 3.0) 和 NSNotificationCenter(swift 2.0)源传递数据
回答by swiftBoy
In Swift 5
在斯威夫特 5
Let's say if want to Receive Data from ViewControllerB to ViewControllerA
假设想从 ViewControllerB 接收数据到 ViewControllerA
ViewControllerA (Receiver)
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 (Sender)
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)
}
}
回答by Deepak Thakur
In swift 2.2 - XCode 7.3, we use #selector
for NSNotificationCenter
在 swift 2.2 - XCode 7.3 中,我们使用#selector
forNSNotificationCenter
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(rotate), name: UIDeviceOrientationDidChangeNotification, object: nil)
回答by Pankaj Jangid
We should remove notification also.
我们也应该删除通知。
Ex.
前任。
deinit
{
NotificationCenter.default.removeObserver(self, name:NSNotification.Name(rawValue: "notify"), object: nil)
}
回答by leanne
I'm able to do one of the following to successfully use a selector - withoutannotating anything with @objc:
我可以执行以下操作之一来成功使用选择器 -无需使用 @objc 注释任何内容:
NSNotificationCenter.defaultCenter().addObserver(self,
selector:"batteryLevelChanged:" as Selector,
name:"UIDeviceBatteryLevelDidChangeNotification",
object:nil)
OR
或者
let notificationSelector: Selector = "batteryLevelChanged:"
NSNotificationCenter.defaultCenter().addObserver(self,
selector: notificationSelector,
name:"UIDeviceBatteryLevelDidChangeNotification",
object:nil)
My xcrun version shows Swift 1.2, and this works on Xcode 6.4 and Xcode 7 beta 2 (which I thought would be using Swift 2.0):
我的 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)