Send and receive messages through NSNotificationCenter in Objective-C?

404,307

Solution 1

@implementation TestClass

- (void) dealloc
{
    // If you don't remove yourself as an observer, the Notification Center
    // will continue to try and send notification objects to the deallocated
    // object.
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super dealloc];
}

- (id) init
{
    self = [super init];
    if (!self) return nil;

    // Add this instance of TestClass as an observer of the TestNotification.
    // We tell the notification center to inform us of "TestNotification"
    // notifications using the receiveTestNotification: selector. By
    // specifying object:nil, we tell the notification center that we are not
    // interested in who posted the notification. If you provided an actual
    // object rather than nil, the notification center will only notify you
    // when the notification was posted by that particular object.

    [[NSNotificationCenter defaultCenter] addObserver:self
        selector:@selector(receiveTestNotification:) 
        name:@"TestNotification"
        object:nil];

    return self;
}

- (void) receiveTestNotification:(NSNotification *) notification
{
    // [notification name] should always be @"TestNotification"
    // unless you use this method for observation of other notifications
    // as well.

    if ([[notification name] isEqualToString:@"TestNotification"])
        NSLog (@"Successfully received the test notification!");
}

@end

... somewhere else in another class ...

- (void) someMethod
{

    // All instances of TestClass will be notified
    [[NSNotificationCenter defaultCenter] 
        postNotificationName:@"TestNotification" 
        object:self];

}

Solution 2

To expand upon dreamlax's example... If you want to send data along with the notification

In posting code:

NSDictionary *userInfo = 
[NSDictionary dictionaryWithObject:myObject forKey:@"someKey"];
[[NSNotificationCenter defaultCenter] postNotificationName: 
                       @"TestNotification" object:nil userInfo:userInfo];

In observing code:

- (void) receiveTestNotification:(NSNotification *) notification {

    NSDictionary *userInfo = notification.userInfo;
    MyObject *myObject = [userInfo objectForKey:@"someKey"];
}

Solution 3

This one helped me:

// Add an observer that will respond to loginComplete
[[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(showMainMenu:) 
                                                 name:@"loginComplete" object:nil];


// Post a notification to loginComplete
[[NSNotificationCenter defaultCenter] postNotificationName:@"loginComplete" object:nil];


// the function specified in the same class where we defined the addObserver
- (void)showMainMenu:(NSNotification *)note {
    NSLog(@"Received Notification - Someone seems to have logged in"); 
}

Source: http://www.smipple.net/snippet/Sounden/Simple%20NSNotificationCenter%20example

Solution 4

There is also the possibility of using blocks:

NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[[NSNotificationCenter defaultCenter] 
     addObserverForName:@"notificationName" 
     object:nil
     queue:mainQueue
     usingBlock:^(NSNotification *notification)
     {
          NSLog(@"Notification received!");
          NSDictionary *userInfo = notification.userInfo;

          // ...
     }];

Apple's documentation

Solution 5

if you're using NSNotificationCenter for updating your view, don't forget to send it from the main thread by calling dispatch_async:

dispatch_async(dispatch_get_main_queue(),^{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"my_notification" object:nil];
});
Share:
404,307
Admin
Author by

Admin

Updated on July 08, 2022

Comments

  • Admin
    Admin almost 2 years

    I am attempting to send and receive messages through NSNotificationCenter in Objective-C. However, I haven't been able to find any examples on how to do this. How do you send and receive messages through NSNotificationCenter?

  • fulvio
    fulvio over 13 years
    Just wondering where [NSNotificationCenter defaultCenter] is meant to placed. Is it best to place it in your AppDelegate?
  • TOMKA
    TOMKA over 13 years
    @Fulvio: It depends, if you are receiving or posting notifications that potentially affect all parts of your application, put it in your AppDelegate. If you are receiving/posting notifications that only affect a single class, put it in that class instead.
  • Aram Kocharyan
    Aram Kocharyan over 12 years
    Also, note that "The method specified by notificationSelector must have one and only one argument (an instance of NSNotification)". I initially assumed that you could provide a selector without an argument and forgo the NSNotification.
  • RomanHouse
    RomanHouse about 12 years
    TestNotification must be NSString type. Is it an instance variable NSNotification?
  • why
    why over 11 years
    Can I access observer self in receiveTestNotification method ?
  • TOMKA
    TOMKA about 11 years
    This is a good update to my answer which is fairly outdated now. With the introduction or ARC and blocks, notification centres are much easier to deal with.
  • Andrew
    Andrew almost 11 years
    I thought so too, but it turns out that it's too good to be true. In this case you have to retain the observer that addObserver returns and later on remove that, which makes it as complicated as creating a new method, if not more so. More info: toastmo.com/blog/2012/12/04/…
  • Nat
    Nat over 10 years
    @dreamlax Truth, however it's worth noticing because this question is mostly searched by new ios devs who keep the notification listener alive longer than they need. Now with arc you usually don't use dealloc and as a result some may think they don't have to release the listener.
  • Fattie
    Fattie over 10 years
    dream, perhaps you should consider also adding the definitive example for a distrubuted notification.
  • tommys
    tommys over 10 years
    It might also be worth mentioning that the [super dealloc] call in the dealloc-method is not permitted under ARC; the rest is all good.
  • Michael Peterson
    Michael Peterson almost 10 years
    why - Yes. receiveTestNotification is an instance method, and you have access to the instance itself via self within it.
  • Maxim Kholyavkin
    Maxim Kholyavkin over 9 years
    NB! if supposing multithread then placing removeObserver to dealloc is not so good idea. Here simple example to crash: lapcatsoftware.com/articles/…
  • hasan
    hasan over 9 years
    That's it. I was looking for a way to get the UserInfo from the receiver method.
  • hasan
    hasan over 9 years
    It seems that all that observer idea doesn't cover all cases. this didn't work when the app. was closed and a notification form the notification centre got tapped. observer method doesn't get called.
  • hasan
    hasan over 9 years
    It seems that all that observer idea doesn't cover all cases. this didn't work when the app. was closed and a notification form the notification centre got tapped. observer method doesn't get called.
  • hasan
    hasan over 9 years
    I already do all that. I want to know the best way to open the view controller. I am enhancing code now. I may get back to here with a question when I finish.
  • superpuccio
    superpuccio over 9 years
    What happen if the notification fires and there are no observers? Is notification lost? Or is it "saved" somewhere ready to be shipped to a new observer (created later)?
  • TOMKA
    TOMKA over 9 years
    @superpuccio: If there are no observers, then nothing happens, the NSNotification is simply discarded.
  • zeal
    zeal about 9 years
    @P1X3L5 Hey dude can you tell me what is the use of <object> argument in adding a observer or posting a notification, since one can pass the date in userinfo
  • Archit Kapoor
    Archit Kapoor over 8 years
    @dreamlax: I am facing an issue with your code. In my simple app, there are two viewcontrollers. In the first VC, I have given a button, which when pressed, sends out the 'TestNotification' and performs a segue to the other VC, which is the Observer in my case. I have declared the observer as self in this and rest, as is your code.The problem is the method 'receiveTestNotification' doesn't gets called at all..! Not even once! It doesn't gets called anyway. And I have crossed checked with your code,so there is hardly any difference.So, would you mind helping me or guide appropriately.
  • TOMKA
    TOMKA over 8 years
    @ArchitKapoor: Check to make sure you are not posting the notification from a background thread. You can only update the user interface from the main thread.
  • Archit Kapoor
    Archit Kapoor over 8 years
    @dreamlax: The notification is posted from the main thread; when the button is pressed an IBAction is called where in I post the notification and perform the segue thereafter in the same method. The code where I am posting the Notification is: [[NSNotificationCenter defaultCenter] postNotificationName:@"TestNotification" object:[[ObserverViewController alloc] init]];
  • Archit Kapoor
    Archit Kapoor over 8 years
    @dreamlax: I also tried this: [[NSNotificationCenter defaultCenter] postNotificationName:@"TestNotification" object:self]; But my efforts went in vain.
  • Crashalot
    Crashalot about 8 years
    is it the notification post that needs to occur from the main thread, or just when you actually update the view, i.e., inside the method receiving the notification you dispatch to the main thread?
  • eiran
    eiran about 8 years
    the thread you send the notification from is the thread running the functions, and thus trying to change the UI. you can also use the dispatch to the main thread inside the functions, just like you said:D. should have the same result, perheps it's even better:D
  • Michael Peterson
    Michael Peterson about 8 years
    @zeal I've never used the <object> argument. From the documentation it is described as "The object posting the notification." That may be useful if multiple objects were posting the same notification and you needed to take different action based on where it originated from. developer.apple.com/library/mac/documentation/Cocoa/Referenc‌​e/…
  • Michael Peterson
    Michael Peterson over 7 years
    @YumYumYum could you post a little more of the code you're having a problem with and detail about the error you get?
  • Pedro Trujillo
    Pedro Trujillo over 5 years
    To avoid the message "ARC forbids explicit message send of 'dealloc' " just remove the invocation to its super class[super dealloc], like: -(void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } also add the observer to the main queue to avoid more problems.
  • Arshad Shaik
    Arshad Shaik almost 5 years
    @eiran, thank you so much bro, it worked only after i wrote inside dispatch_async