The private AppSupport framework on iOS has a class called CPDistributedNotificationCenter which appears to support a subset of the functionality provided by NSDistributedNotificationCenter on OS X.
I’m attempting to use this class to post notifications from a background daemon such that multiple clients in other processes can receive these notifications and act on them. I realize there are other options, including CPDistributedMessagingCenter or CFMessagePort, low level mach ports or even darwin’s notify_post. I’d prefer it if the daemon had no knowledge of the clients however, and I’d like to be able to pass data along with the notification, and notify_post does not allow this.
Currently, this is what I am doing in the daemon:
CPDistributedNotificationCenter* center;
center = [CPDistributedNotificationCenter centerNamed:@"com.yfrancis.notiftest"];
[center runServer];
[center postNotificationName:@"hello"];
And in the client:
CPDistributedNotificationCenter* center;
center = [CPDistributedNotificationCenter centerNamed:@"com.yfrancis.notiftest"];
[center startDeliveringNotificationsToMainThread];
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc addObserver:[Listener new]
selector:@selector(gotNotification:)
name:@"hello"
object:nil];
where Listener is a simple class that implements a single method gotNotification:
Unfortunately, the client never receives the ‘hello’ notification. If I replace the name argument in the addObserver call with nil I can see every notification delivered to the client’s notification center, but ‘hello’ is not one of them.
I got the inspiration for my code by looking at a disassembly of SpringBoard and CPDistributedNotificationCenter. Notifications appear to be delivered via CPDistributedNotificationCenter‘s deliverNotification:userInfo: which acts as a shim for NSNotificationCenter‘s postNotificationName:object:userInfo:.
What am I missing here?
Figured it out. Your daemon has to wait for a notification indicating that a client has started listening, before sending out your notification. There is no backlog, even if the daemon server runs before the client, there is a registration delay. You can’t simply start your server and immediately post notifications to listeners. The following works for me:
In the server init:
And make sure to implement the following method in the server:
I’ve documented this API on the iPhoneDevWiki