Local Notifications

In this post I’ll show you the basics for working with local notifications, which are notifications generated from the device itself, versus a remote notification (aka push notification) that is sent from a remote server. Local notifications are useful when you need to schedule a reminder or otherwise notify the user of a future event.

Creating and Processing Local Notifications

Local notifications are scheduled for a future date by creating a UILocalNotification object. When creating the notification you can also specify the type of notification(s) to send, a badge, alert or sound.

If a local notification arrives on the application that is not running in the foreground, the notification is delivered (that is, the alert shown, the badge set, sound played). If the notification is an alert, a dialog is shown to the user, along with an option to open the application. If the user chooses to open the app, the method didFinishLaunchingWithOptions in the application delegate is called passing in the local notification object.

If the application is running when a local notification is received, the method didReceiveLocalNotification is called, again, passing in the local notification object.

Screenshots

The app I’ve written to work with notification has a range of buttons to schedule various types of notifications:

Once you choose an option, the notification is scheduled – to keep things simple, in my application I’ve set all notifications to arrive in 60 seconds. The screenshot below shows an incoming notification when the app has been put into the background.

The screenshot below is an alert I display from within the method called when a notification arrives.

Methods in the App Delegate

The application delegate contains the two methods needed for managing incoming notifications. The method didFinishLaunchingWithOptions is shown below. Notice the check of the launchOptions parameter early in the method, if this value is nil, this is a standard application startup. If the value is not nil, the application was started based on a notification presented to the user – in this case I show an alert along with a few debug messages, including the payload data received from the notification (more on this below).

The code in the later half of the method is typical startup stuff, creating a window and view controller, etc

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  // Handle launching from a notification
  UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
 
  // If not nil, the application was based on an incoming notifiation
  if (notification) 
  {
    NSLog(@"Notification initiated app startup");
 
    // Access the payload content
    NSLog(@"Notification payload: %@", [notification.userInfo objectForKey:@"payload"]);
 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Launched with Options" 
                              message:@"Notification initiated app startup" 
                              delegate:self cancelButtonTitle:@"Ok" 
                              otherButtonTitles:nil];
    [alert show];
    [alert release];
  }
 
  // Reset the badge
  [application setApplicationIconBadgeNumber:0];
 
  // Create and initialize the window
  window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
 
  // Create test view controller
  vc = [[TestViewController alloc] init];
 
  [window addSubview:vc.view];
  [window makeKeyAndVisible];
 
  return YES;
}

The second method in the application delegate is didReceiveLocalNotification which will be called when a notification arrives while the applications is running. In this method I show an alert and also write the notification payload to the debug console. For the payload, I am creating an array of objects, packaging the array within a dictionary and passing the later along with the notification.

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification 
{
  UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Launched with Options" 
                            message:@"Incoming notification in running app" 
                            delegate:self cancelButtonTitle:@"Ok" 
                            otherButtonTitles:nil];
  [alert show];
  [alert release];
 
  NSLog(@"Incoming notification in running app");
 
  // Access the payload content
  NSLog(@"Notification payload: %@", [notification.userInfo objectForKey:@"payload"]);
}
Scheduling a Local Notification

The buttons shown in the screenshot above are how we initiate creating and scheduling a local notification. Before handling each event there is some common code for creating a UILocalNotification object, setting the fire date and populating the data (payload) that will accompany the notification.

- (void)buttonPressed:(UIButton *)button
{
  UILocalNotification *localNotification = [[[UILocalNotification alloc] init] autorelease];
 
  if (!localNotification) 
    return;
 
  // Current date
  NSDate *date = [NSDate date]; 
 
  // Add one minute to the current time
  NSDate *dateToFire = [date dateByAddingTimeInterval:60];
 
  // Set the fire date/time
  [localNotification setFireDate:dateToFire];
  [localNotification setTimeZone:[NSTimeZone defaultTimeZone]];
 
  // Create a payload to go along with the notification
  NSArray *array = [NSArray arrayWithObjects:@"Value 1", @"Value 2", nil];
  NSDictionary *data = [NSDictionary dictionaryWithObject:array forKey:@"payload"];
  [localNotification setUserInfo:data];
 
  if (button == buttonAlert || button == buttonAll)
  {	
    // Setup alert notification
    [localNotification setAlertBody:@"Incoming Local Notification" ];
    [localNotification setAlertAction:@"Open App"];
    [localNotification setHasAction:YES];      
  }
 
  if (button == buttonBadge || button == buttonAll)
  {
    // Set badge notification, increment current badge value
    [localNotification setApplicationIconBadgeNumber:[[UIApplication sharedApplication] applicationIconBadgeNumber] + 1];
  }
 
  if (button == buttonSound || button == buttonAll)
  {
    // Setup sound notification
    [localNotification setSoundName:UILocalNotificationDefaultSoundName];			  
  }
 
  // Schedule the notification        
  [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
}
Local Notification Xcode Project

Download Xcode Local Notification Example

    • I did notice the documentation states 0 = no change, however, in my testing and previous work with badges, 0 did clear the badge on the UI. Strange…

      • In my App I had to explicitly set

        [localNotification setApplicationIconBadgeNumber:-1];

        in order to have the badge removed, once the UILocaNotification is fired. My blog post was written in 4.3.2, however I don’t think they changed this..

  1. I downloaded the source and the sound notification is not working.

    • Where you running the app on a device or the simulator? The sound only works for me when running the application on an iPhone.

      • I haven’t tested in my iPhone, but yes, it works only in the iPhone, why it do not work in the simulator? It’s a strange behavior.

  2. and if i will view the local notification ad scheduled time (for example 6AM, 12AM, and more)..
    how i can do it?

  3. Hello John Muchow , thanks for such a nice tutorial.

    John , i have some problem. i want to set document directory sound file (.wav or .caf ,etc) to local_Notification.soundname ? Is it possible to set ?

    Or

    How can i play audio player as i get local notification. obviously all this ( also [audio_player Play] ) happen when application is in background mode.

    Thanks in Advance.

    • To play a sound you can include the file in the application bundle, and then reference the file name your app.

Comments are closed.