NSNotification, UserInfo and Object Methods

When working with an NSNotification object, you’ll want to familiarize yourself the userInfo dictionary, which provides access to any additional objects that may be of interest to the receiver. Understanding the object method may also be helpful if you are using the same notification on more than one object.

userInfo Dictionary

Below I add an observer for MPMoviePlayerContentPreloadDidFinishNotification, which will send a message to the method moviePreloadDidFinish: when a MoviePlayerController object has finished playing:

mp =  [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
 
[[NSNotificationCenter defaultCenter] addObserver:self 
                     selector:@selector(moviePreloadDidFinish:) 
                     name:MPMoviePlayerContentPreloadDidFinishNotification 
                     object:mp];
}

Here’s how to access and print the userInfo dictionary from the notification object:

- (void) moviePlayBackDidFinish:(NSNotification*)notification 
{
  NSDictionary *userInfo = [notification userInfo];
 
  NSLog(@"MPMoviePlayerPlaybackDidFinishReasonUserInfoKey: %@",
    [userInfo objectForKey:@"MPMoviePlayerPlaybackDidFinishReasonUserInfoKey"]);
 
  ...
}

The value of MoviePlayerPlaybackDidFinishReasonUserInfoKey is an NSNumber object which contains an integer value specifying reason the playback finished. The possible range of return values are defined in MPMovieFinishReason, which is an enum type as shown here:

enum {
   MPMovieFinishReasonPlaybackEnded,
   MPMovieFinishReasonPlaybackError,
   MPMovieFinishReasonUserExited
};
typedef NSInteger MPMovieFinishReason;

Pulling all this together, you could write something similar to the following to check if the user stopped playback of the movie:

if ([[userInfo objectForKey:@"MPMoviePlayerPlaybackDidFinishReasonUserInfoKey"] intValue] == MPMovieFinishReasonUserExited)
    NSLog(@"User stopped playback");
object Method

One more handy method within NSNotification is the method object, which will return the object (as type id) that is associated with the notification. For example, check out the code below that sets up the notification, pay attention to the last parameter mp which is assigned to the object parameter.

mp =  [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
 
[[NSNotificationCenter defaultCenter] addObserver:self 
                     selector:@selector(moviePreloadDidFinish:) 
                     name:MPMoviePlayerContentPreloadDidFinishNotification 
                     object:mp];

Within the method called by the selector, you can now access the object passed in by querying the object method:

- (void) moviePlayBackDidFinish:(NSNotification*)notification 
{
  MPMoviePlayerController *mpObject = (MPMoviePlayerController *) [notification object]; 
...

mpObject will point to the mp object defined in the previous code block – using the object method you can retrieve a pointer to the object that made the original notification request.

  1. Actually, the object method is a bit more complex than you suggest. It does not give you the object that sent the notification; rather, it gives you whatever was assigned in postNotificationName:object. This need not be the notifying object.

    This allows a shortcut, albeit one that some developers would consider poor practice: instead of messing around with the userInfo parameter, just pass the data that the observer needs (an NSString, say) as the object. So long as the relevant data is only a single object and the listeners don’t need to specify a single object to listen to, this will work just fine.

    The advantages of that approach are 1) a tiny increase in efficiency by not having to create the dictionary, release it, put an object into it and pull it out, 2) fewer lines of executable code, 3) not having to create a key that has no other purpose and expose it to both the senders and receivers.

    Also note that there is some unfortunate coupling when you use the standard userInfo-related method: you need a notification string and a set of notification key strings that have to be managed as a unit.

    Ultimately, using the shortcut is a matter of taste. I can understand the distaste some might have for it, but it has its uses.

Comments are closed.