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

IosSwiftSwift3NsnotificationcenterNsnotifications

Ios Problem Overview


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?

Ios Solutions


Solution 1 - Ios

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)

Solution 2 - Ios

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

Solution 3 - Ios

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

Solution 4 - Ios

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)

Solution 5 - Ios

this is how I implement it .

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

Solution 6 - Ios

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.

Solution 7 - Ios

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser3766930View Question on Stackoverflow
Solution 1 - IosSahilView Answer on Stackoverflow
Solution 2 - IosSachin RasaneView Answer on Stackoverflow
Solution 3 - IosIlesh PView Answer on Stackoverflow
Solution 4 - IosWaliDView Answer on Stackoverflow
Solution 5 - IosNitinView Answer on Stackoverflow
Solution 6 - IosWINSergeyView Answer on Stackoverflow
Solution 7 - IosMohammad MuddasirView Answer on Stackoverflow