ChatGPT解决这个技术问题 Extra ChatGPT

How to pass data using NotificationCenter in swift 3.0 and NSNotificationCenter in swift 2.0?

I'm implementing socket.io in my swift ios app.

Currently on several panels I'm listening to the server and wait for incoming messages. I'm doing so by calling the getChatMessage function in each panel:

func getChatMessage(){
    SocketIOManager.sharedInstance.getChatMessage { (messageInfo) -> Void in
        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            //do sth depending on which panel user is
        })
    }
}

However I noticed it's a wrong approach and I need to change it - now I want to start listening for incoming messages only once and when any message comes - pass this message to any panel that listens to it.

So I want to pass the incoming message through the NSNotificationCenter. So far I was able to pass the information that something happened, but not pass the data itself. I was doing that by:

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.showSpinningWheel(_:)), name: showSpinner, object: nil)

then I had a function called:

func showSpinningWheel(notification: NSNotification) {
}

and any time I wanted to call it I was doing:

NSNotificationCenter.defaultCenter().postNotificationName(hideSpinner, object: self)

So how can I pass the object messageInfo and include it in the function that gets called?

use method with userinfo ... NSNotificationCenter.defaultCenter().postNotificationName("hideSpinner", object: nil, userInfo: yourvalue)
hm ok, and how can I fetch this yourValue in the function that gets called on that notification (in showSpinningWheel)?
using .userinfo like notification.userinfo

S
Sahil

Swift 2.0

Pass info using userInfo which is a optional Dictionary of type [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, 4.0, 5.0 version and above

The userInfo now takes [AnyHashable: Any]? as an argument, which we provide as a dictionary literal in 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
 // For swift 4.0 and above put @objc attribute in front of function Definition  
 func showSpinningWheel(_ notification: NSNotification) {

  if let image = notification.userInfo?["image"] as? UIImage {
  // do something with your image   
  }
 }

NOTE: Notification “names” are no longer strings, but are of type Notification.Name, hence why we are using NSNotification.Name(rawValue: "notificationName") and we can extend Notification.Name with our own custom notifications.

extension Notification.Name {
static let myNotification = Notification.Name("myNotification")
}

// and post notification like this
NotificationCenter.default.post(name: .myNotification, object: nil)

S
Sachin Rasane

For 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
            }
        }
 }

For 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
            }
        }
 }

Worked for me Swift 4
D
DoesData

Hello @sahil I update your answer for 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
            }
        }
 }

Hope it's helpful. Thanks


should be notification.userinfo, not notification.object
If you are receiving object/dictionary from objective-c class/notification you must use .object. If you are receiving object from Swift notification use .userInfo. Track you notification if it is .object or .userInfo with: func observerNotification(notification: NSNotification){ print("Notification Received :", notification) }
Make sure if you are sending across threads that you set up the observer on that key before you post to that notification key. You may be more familiar with the terms listener and event.
W
WaliD

This is what worked for me in Swift 5

NotificationCenter.default.addObserver(self,
                                       selector: #selector(handleMassage),
                                       name: Notification.Name("NotificationName"),
                                       object: nil)

The method that handles the notification:

    @objc func handleMassage(notification: NSNotification) {
    if let dict = notification.object as? NSDictionary {
        if let myMessage = dict["myMessage"] as? String{
            myLabel.text = myMessage
        }
    }
}

I posted it like this:

let dic = ["myMessage": "testing"]
NotificationCenter.default.post(name: Notification.Name("NotificationName"), object: dic)

S
Shivam Parmar

this is how I implement it .

let dictionary = self.convertStringToDictionary(responceString)            
     NotificationCenter.default.post(name: NSNotification.Name(rawValue: "SOCKET_UPDATE"), object: dictionary)

W
WINSergey

Swift 5.5 with avoid #selector():

First of all, declare the name:

extension Notification.Name {
    static let prettyName = Notification.Name("MyPrettyName")
}

Next is to add observer (take care with queue):

// 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
}

Finally, we can post the notification from another object

// 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)
    

NOTE: Do NOT forget to remove the observer, when you will not need it anymore.


M
Mohammad Muddasir

In swift 4.2 I used following code to show and hide code using NSNotification

 @objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo? [UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        let keyboardheight = keyboardSize.height
        print(keyboardheight)
    }
}