So, I am just testing NSNotifications on a variety of cases and this one is confusing. I would appreciate it if you could help me understand NSNotifications !
I have a N
The differences you are describing seem to be due to changes in which objects are alive when. Views and view controllers do not exist indefinitely, and are not all created when the app starts. An object has to exist to receive and log a notification. The basic notification system is working as expected.
You should be able to see the effect of lifetime on the messages received if you add log statements announcing when an object that is supposed to receive one of these notifications is created and when it is destroyed within the body of -init
(or whatever the designated initializer of your superclass is) and -dealloc
.
Also: Your log statements will be easier to track down if you tag them with the function doing the logging like NSLog(@"%s: <message>", __func__)
. The compiler generates a string named __func__
for each function that contains the function's name.
I just set up a navigation-based app. In the root controller header, I've got this:
#import <UIKit/UIKit.h>
extern NSString * const EPNotification;
@interface RootViewController : UITableViewController {
}
@end
All I really did different there was set up a string to be used throughout the code. Then in the root implementation file, I have this (plus all the standard stuff):
#import "RootViewController.h"
#import "One.h"
NSString *const EPNotification = @"Notification"; // this will be the global string name for the notification
@implementation RootViewController
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(gotNotification:) name:EPNotification
object:nil];
UIBarButtonItem *next = [[UIBarButtonItem alloc] initWithTitle:@"next" style:UIBarButtonItemStylePlain target:self action:@selector(sendNotification)];
self.navigationItem.rightBarButtonItem = next;
[next release];
}
- (void)sendNotification {
NSDictionary *d = [NSDictionary dictionaryWithObject:@"view 1" forKey:@"sender"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"Notification" object:self userInfo:d];
One *o = [[One alloc] initWithNibName:@"One" bundle:nil];
[self.navigationController pushViewController:o animated:YES];
[o release];
}
- (void)gotNotification:(NSNotification *)note {
NSLog(@"from %@", [[note userInfo] objectForKey:@"sender"]);
}
I've got 3 other views (One, Two and Three, respectively), that are pretty much all exactly the same. Nothing in the header (besides the standard stuff). I'll post one of the .m files so you can see the setup.
#import "One.h"
#import "Two.h"
@implementation One
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *next = [[UIBarButtonItem alloc] initWithTitle:@"next" style:UIBarButtonItemStylePlain
target:self action:@selector(sendNotification)];
self.navigationItem.rightBarButtonItem = next;
[next release];
}
- (void)sendNotification {
NSDictionary *d = [NSDictionary dictionaryWithObject:@"view 2" forKey:@"sender"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"Notification" object:self userInfo:d];
Two *t = [[Two alloc] initWithNibName:@"Two" bundle:nil];
[self.navigationController pushViewController:t animated:YES];
[t release];
}
And honestly, that's pretty much it. On my class Three, I pop to the root controller instead of create a new view controller, but that's it. It tells you which view you're on with each click of the button, so hopefully it'll help you understand better how notifications work.
"The first time when you send the notification, other view controllers don't exist. They haven't been created yet. The viewController is still nil yet. Since there is no observer object, you don't get any logs. Second time around, both objects in the view controllers have been created. So they receive the notification as they are alive and the log the received notification statements."