Как передать данные с помощью NotificationCenter в Swift 3.0 и NSNotificationCenter в Swift 2.0?
Я реализую socket.io
в моем быстром приложении IOS.
В настоящее время на нескольких панелях я слушаю сервер и жду входящих сообщений. Я делаю это, называя getChatMessage
функция в каждой панели:
func getChatMessage(){
SocketIOManager.sharedInstance.getChatMessage { (messageInfo) -> Void in
dispatch_async(dispatch_get_main_queue(), { () -> Void in
//do sth depending on which panel user is
})
}
}
Однако я заметил, что это неправильный подход, и мне нужно изменить его - теперь я хочу начать прослушивать входящие сообщения только один раз, а когда приходит любое сообщение - передать это сообщение любой панели, которая его слушает.
Поэтому я хочу передать входящее сообщение через NSNotificationCenter. До сих пор мне удавалось передавать информацию о том, что что-то произошло, но не передавать сами данные. Я делал это путем:
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.showSpinningWheel(_:)), name: showSpinner, object: nil)
тогда у меня была функция под названием:
func showSpinningWheel(notification: NSNotification) {
}
и всякий раз, когда я хотел позвонить, я делал:
NSNotificationCenter.defaultCenter().postNotificationName(hideSpinner, object: self)
Так как я могу передать объект messageInfo
и включить его в функцию, которая вызывается?
7 ответов
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
}
}
ПРИМЕЧАНИЕ. "Имена" уведомлений больше не являются строками, а имеют тип Notification.Name, поэтому мы и используем NSNotification.Name(rawValue:"notificationName")
и мы можем расширить Notification.Name с нашими собственными пользовательскими уведомлениями.
extension Notification.Name {
static let myNotification = Notification.Name("myNotification")
}
// and post notification like this
NotificationCenter.default.post(name: .myNotification, object: nil)
Для Swift 3
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) {
print(notification.userInfo ?? "")
if let dict = notification.userInfo as NSDictionary? {
if let id = dict["image"] as? UIImage{
// do something with your image
}
}
}
Для Swift 4
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
@objc func showSpinningWheel(_ notification: NSNotification) {
print(notification.userInfo ?? "")
if let dict = notification.userInfo as NSDictionary? {
if let id = dict["image"] as? UIImage{
// do something with your image
}
}
}
Здравствуйте @sahil Я обновляю ваш ответ для Swift 3
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) {
print(notification.userInfo ?? "")
if let dict = notification.userInfo as NSDictionary? {
if let id = dict["image"] as? UIImage{
// do something with your image
}
}
}
Надеюсь, это полезно. Спасибо
Это то, что у меня сработало в Swift 5
NotificationCenter.default.addObserver(self,
selector: #selector(handleMassage),
name: Notification.Name("NotificationName"),
object: nil)
Метод, обрабатывающий уведомление:
@objc func handleMassage(notification: NSNotification) {
if let dict = notification.object as? NSDictionary {
if let myMessage = dict["myMessage"] as? String{
myLabel.text = myMessage
}
}
}
Я разместил это так:
let dic = ["myMessage": "testing"]
NotificationCenter.default.post(name: Notification.Name("NotificationName"), object: dic)
Swift 5.5 с избеганием
#selector()
:
Прежде всего, объявите имя:
extension Notification.Name {
static let prettyName = Notification.Name("MyPrettyName")
}
Далее нужно добавить наблюдателя (осторожно с очередью):
// For example transferred data should implement protocol
protocol PrettyDelegate {
func doSomethingAwesome()
}
// Here is the way how we can subscribe as observer
NotificationCenter.default.addObserver(forName: .prettyName, object: nil, queue: nil) { [weak self] notif in
guard let self = self else { return } // Because self used more than once
if let userInfo = notif.userInfo,
let delegate = userInfo["pretty"] as? PrettyDelegate {
self.delegate = delegate
}
self.makePretty() // Here we can do anything
}
Наконец, мы можем опубликовать уведомление от другого объекта.
// Here I'll illustrate how to pass optional value as userInfo
var userInfo: [AnyHashable : Any]?
if let prettyDelegate = self as? PrettyDelegate {
userInfo = ["pretty": prettyDelegate]
}
NotificationCenter.default.post(name: .prettyName, object: nil, userInfo: userInfo)
ПРИМЕЧАНИЕ: НЕ забудьте удалить наблюдатель, когда он вам больше не понадобится.
let dictionary = self.convertStringToDictionary(responseceString)
NotificationCenter.default.post (имя: NSNotification.Name(rawValue: "SOCKET_UPDATE"), объект: словарь)
В Swift 4.2 я использовал следующий код, чтобы показать и скрыть код с помощью NSNotification
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo? [UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
let keyboardheight = keyboardSize.height
print(keyboardheight)
}
}