Wednesday, October 21, 2009

You've been served!


Here is a simple example of posting and observing Notifications. It's a simple document-based application. There is an instance variable and a method declaration in the header:


@interface MyDocument : NSDocument
{
int i;
}
- (void)myCallback:(NSNotification *)note;
@end


And the code in the MyDocument.m implementation has just a little bit added to what the template gives. The top of thefile and the first part of init is:


@implementation MyDocument

int N = 0;
NSNotificationCenter *nc;
NSString *DocNotification = @"hey you!";

- (id)init
{
self = [super init];
if (self) {
nc = [NSNotificationCenter defaultCenter];
N++;
i = N;
NSLog(@"init %@ # %i ", self, i);


There is a class variable N that is incremented each time init is called. The instantiated document saves the current value of N in its instance variable i. We declare and get a pointer to the default notification center, and log the fact that we're alive. And we declare a string (which should probably be like what Hillegass does:
extern NSString * const BNRColorChangedNotification;).

The interesting bit is next. It's a little fancy, we're using a dictionary called userInfo, which could be used to tell everybody everything. We could do without it.


        NSDictionary *D = [NSDictionary 
dictionaryWithObject:
[NSNumber numberWithInt:i]
forKey:@"N"];

[nc postNotificationName:DocNotification
object:self
userInfo:D];

SEL sel = @selector(myCallback:);
[nc addObserver:self
selector:sel
name:DocNotification
object:nil];
}
return self;
}

- (void)myCallback:(NSNotification *)note {
NSLog(@"%@ #%i received %@", self, i, note);
}


The object (which is just nil above) could be used to inform the notification center that we are only interested in notifications that involve one particular object. Instead, here we get notifications for all the windows that are created.

Finally, we should do [nc removeObserver:self] in dealloc.

Here is the output (log info removed and reformatted). When the app launches we get the log from the init method:


Notified[2219:80f] init <MyDocument: 0x131b60> # 1


We create a second document, and following the log, the first document has received the notification of the second one's creation. It gets a pointer to the new document, which could be used for further communication.


Notified[2219:80f] init <MyDocument: 0x141080> # 2 

Notified[2219:80f] <MyDocument: 0x131b60> #1 received
NSConcreteNotification 0x22dc10 {name = hey you!;
object = <MyDocument: 0x141080>;
userInfo = { N = 2; }}


Now we create a third document, and following the log, both the first and second documents have received the notification of the third one's creation:


Notified[2219:80f] init <MyDocument: 0x141290> # 3 

Notified[2219:80f] <MyDocument: 0x131b60> #1 received
NSConcreteNotification 0x111d30 {name = hey you!;
object = <MyDocument: 0x141290>;
userInfo = { N = 3; }}

Notified[2219:80f] <MyDocument: 0x141080> #2 received
NSConcreteNotification 0x111d30 {name = hey you!;
object = <MyDocument: 0x141290>;
userInfo = { N = 3; }}