How to pass object with NSNotificationCenter

前端 未结 5 1133
广开言路
广开言路 2020-11-28 18:42

I am trying to pass an object from my app delegate to a notification receiver in another class.

I want to pass integer messageTotal. Right now I have:<

相关标签:
5条回答
  • 2020-11-28 19:21

    Swift 5.1 Custom Object/Type

    // MARK: - NotificationName
    // Extending notification name to avoid string errors.
    extension Notification.Name {
        static let yourNotificationName = Notification.Name("yourNotificationName")
    }
    
    
    // MARK: - CustomObject
    class YourCustomObject {
        // Any stuffs you would like to set in your custom object as always.
        init() {}
    }
    
    // MARK: - Notification Sender Class
    class NotificatioSenderClass {
    
         // Just grab the content of this function and put it to your function responsible for triggering a notification.
        func postNotification(){
            // Note: - This is the important part pass your object instance as object parameter.
            let yourObjectInstance = YourCustomObject()
            NotificationCenter.default.post(name: .yourNotificationName, object: yourObjectInstance)
        }
    }
    
    // MARK: -Notification  Receiver class
    class NotificationReceiverClass: UIViewController {
        // MARK: - ViewController Lifecycle
        override func viewDidLoad() {
            super.viewDidLoad()
            // Register your notification listener
            NotificationCenter.default.addObserver(self, selector: #selector(didReceiveNotificationWithCustomObject), name: .yourNotificationName, object: nil)
        }
    
        // MARK: - Helpers
        @objc private func didReceiveNotificationWithCustomObject(notification: Notification){
            // Important: - Grab your custom object here by casting the notification object.
            guard let yourPassedObject = notification.object as? YourCustomObject else {return}
            // That's it now you can use your custom object
            //
            //
    
        }
          // MARK: - Deinit
      deinit {
          // Save your memory by releasing notification listener
          NotificationCenter.default.removeObserver(self, name: .yourNotificationName, object: nil)
        }
    
    
    
    
    }
    
    
    0 讨论(0)
  • 2020-11-28 19:28

    You'll have to use the "userInfo" variant and pass a NSDictionary object that contains the messageTotal integer:

    NSDictionary* userInfo = @{@"total": @(messageTotal)};
    
    NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
    [nc postNotificationName:@"eRXReceived" object:self userInfo:userInfo];
    

    On the receiving end you can access the userInfo dictionary as follows:

    -(void) receiveTestNotification:(NSNotification*)notification
    {
        if ([notification.name isEqualToString:@"TestNotification"])
        {
            NSDictionary* userInfo = notification.userInfo;
            NSNumber* total = (NSNumber*)userInfo[@"total"];
            NSLog (@"Successfully received test notification! %i", total.intValue);
        }
    }
    
    0 讨论(0)
  • 2020-11-28 19:32

    Swift 5

    func post() {
        NotificationCenter.default.post(name: Notification.Name("SomeNotificationName"), 
            object: nil, 
            userInfo:["key0": "value", "key1": 1234])
    }
    
    func addObservers() {
        NotificationCenter.default.addObserver(self, 
            selector: #selector(someMethod), 
            name: Notification.Name("SomeNotificationName"), 
            object: nil)
    }
    
    @objc func someMethod(_ notification: Notification) {
        let info0 = notification.userInfo?["key0"]
        let info1 = notification.userInfo?["key1"]
    }
    

    Bonus (that you should definitely do!) :

    Replace Notification.Name("SomeNotificationName") with .someNotificationName:

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

    Replace "key0" and "key1" with Notification.Key.key0 and Notification.Key.key1:

    extension Notification {
      enum Key: String {
        case key0
        case key1
      }
    }
    

    Why should I definitely do this ? To avoid costly typo errors, enjoy renaming, enjoy find usage etc...

    0 讨论(0)
  • 2020-11-28 19:36

    Swift 2 Version

    As @Johan Karlsson pointed out... I was doing it wrong. Here's the proper way to send and receive information with NSNotificationCenter.

    First, we look at the initializer for postNotificationName:

    init(name name: String,
       object object: AnyObject?,
     userInfo userInfo: [NSObject : AnyObject]?)
    

    source

    We'll be passing our information using the userInfo param. The [NSObject : AnyObject] type is a hold-over from Objective-C. So, in Swift land, all we need to do is pass in a Swift dictionary that has keys that are derived from NSObject and values which can be AnyObject.

    With that knowledge we create a dictionary which we'll pass into the object parameter:

     var userInfo = [String:String]()
     userInfo["UserName"] = "Dan"
     userInfo["Something"] = "Could be any object including a custom Type."
    

    Then we pass the dictionary into our object parameter.

    Sender

    NSNotificationCenter.defaultCenter()
        .postNotificationName("myCustomId", object: nil, userInfo: userInfo)
    

    Receiver Class

    First we need to make sure our class is observing for the notification

    override func viewDidLoad() {
        super.viewDidLoad()
    
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("btnClicked:"), name: "myCustomId", object: nil)   
    }
        
    

    Then we can receive our dictionary:

    func btnClicked(notification: NSNotification) {
       let userInfo : [String:String!] = notification.userInfo as! [String:String!]
       let name = userInfo["UserName"]
       print(name)
    }
    
    0 讨论(0)
  • 2020-11-28 19:37

    Building on the solution provided I thought it might be helpful to show an example passing your own custom data object (which I've referenced here as 'message' as per question).

    Class A (sender):

    YourDataObject *message = [[YourDataObject alloc] init];
    // set your message properties
    NSDictionary *dict = [NSDictionary dictionaryWithObject:message forKey:@"message"];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationMessageEvent" object:nil userInfo:dict];
    

    Class B (receiver):

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        [[NSNotificationCenter defaultCenter]
         addObserver:self selector:@selector(triggerAction:) name:@"NotificationMessageEvent" object:nil];
    }
    
    #pragma mark - Notification
    -(void) triggerAction:(NSNotification *) notification
    {
        NSDictionary *dict = notification.userInfo;
        YourDataObject *message = [dict valueForKey:@"message"];
        if (message != nil) {
            // do stuff here with your message data
        }
    }
    
    0 讨论(0)
提交回复
热议问题