Way back when, everyone was still complaining about Apple’s lack of support for 3rd party multitasking, there was a simple solution put into place. This solution was known as push notifications.
Push notifications solved many of the issues associated with background processing. For example, when quitting the AIM application, the server could keep you logged in and send you a push notification when a new message arrived. You could then tap on a View button that would launch the app and start chatting away.
This solution is great and all, but it still required and internet connection. As of iOS4′s release, Apple has introduced a new type of notification that can be scheduled to fire within the device itself. It requires no complicated server programming, or additional configuration with iTunes. I am talking about Local Notifications.
Local notifications can be scheduled on the user’s iDevice to fire at any given time; you can even set them to be recurring. Today, we will explore these notifications and I will provide you with a simple example of how to schedule, view, and handle local notifications.
The project will allow a user to schedule a location notification to fire off at a given date. They are also able to specify some text for the notification using the input text field. The table view (click here for the table view tutorial) displays a list of all of the currently scheduled location notifications within the application.
Lets get started!
1. Create a View-Based Application and give it a name of “LocalNotification“
2.Now create all the IBOutlets, properties, and action.
IBOutlet UITableView *table;
IBOutlet UIDatePicker *datePicker;
IBOutlet UITextField *textField;
@property (nonatomic, retain) IBOutlet UITableView *table;
@property (nonatomic, retain) IBOutlet UIDatePicker *datePicker;
@property (nonatomic, retain) IBOutlet UITextField *textField;
-(IBAction)alarm;
Seems clear enough. We have three UI elements that we care about and one action. One thing to note is, your class should implement the UITableViewDelegate and UITableViewDataSource protocols.
3. Now it’s time to build our interface. Open Interface builder and construct an interface like this.
4. After creating the interface, make sure you hook up all of the UI components to their corresponding IBOutlets and hook up the alarm action by click on the textfield and connecting the Did End On Exit response to your action.
5. Also, don’t forget to link the Delegate and Data Source for you table to the files owner.
6. Now it’s time to implement the Table View delegate methods just like we have done in the past on the table view tutorial.
– (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
– (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
in the array of notifications.
return [[[UIApplication sharedApplication] scheduledLocalNotifications] count];
}
– (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *Cell = @”SimpleTableViewCell”;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:Cell];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:Cell] autorelease];
}
NSArray *notificationArray = [[UIApplication sharedApplication] scheduledLocalNotifications];
UILocalNotification *notif = [notificationArray objectAtIndex:indexPath.row];
[cell.textLabel setText:notif.alertBody];
[cell.detailTextLabel setText:[notif.fireDate description]];
return cell;
}
So, the new code here is dealing with retrieving a list of scheduled notifications. Calling the scheduledLocalNotifications method of UIApplication will return an NSArray of all notifications scheduled by the current app. We just index into this array and grab each notification.
By now, you should be fairly familiar with how table views work.
Finally, we are displaying the alertBody (text that displays when the notification fires) and the fireDate (date and time when the notification will display) in the tableview cell.
Oh, hey, don’t forget to synthesize your properties!
And now for the moment you’ve been waiting for… OK, probably not, but definitely the most exciting part of this tutorial. Let’s implement that alarm IBAction that you declared earlier.
7. Update your .m file to contain the following code.
-(IBAction)alarm {
[textField resignFirstResponder];
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
// Get the current date
NSDate *pickerDate = [self.datePicker date];
// Break the date up into components
NSDateComponents *dateComponents = [calendar components:( NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit )
fromDate:pickerDate];
NSDateComponents *timeComponents = [calendar components:( NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit )
fromDate:pickerDate];
// Set up the fire time
NSDateComponents *dateComps = [[NSDateComponents alloc] init];
[dateComps setDay:[dateComponents day]];
[dateComps setMonth:[dateComponents month]];
[dateComps setYear:[dateComponents year]];
[dateComps setHour:[timeComponents hour]];
[dateComps setMinute:[timeComponents minute]];
[dateComps setSecond:[timeComponents second]];
NSDate *itemDate = [calendar dateFromComponents:dateComps];
[dateComps release];
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.fireDate = itemDate;
localNotif.timeZone = [NSTimeZone defaultTimeZone];
// Set the action button
localNotif.alertAction = @”View”
//This sets the alert text to the current text in the textfield.
localNotif.alertBody = [textField text];
//This sets the sound name of the notification.
localNotif.soundName = UILocalNotificationDefaultSoundName;
//You can also set the badge number of the application.
localNotif.applicationIconBadgeNumber = 1;
// Schedule the notification
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
[localNotif release];
[self.table reloadData];
}
So, most of the explanation is in the comments, but I’ll talk you through some of the less obvious stuff. The first tricky area is dealing with the NSCalendar. We just use the NSCalendar object to break the date up into components. Note: This demo does not require that we break the date up into components. You could have just as easily fed the date from the date picker into the notification fireDate. The reason that I’m showing you how to break it down is, you may have some sort of custom date logic to work with and this makes things much easier in the future.
Another important bit of code is where we set the alertBody. In this example we set it to the text that the user entered into the text field. You can set this to whatever you like.
After actually scheduling the notification, we just reload the tableview to get it to display immediately.
The last piece of this puzzle is determining what to do when a notification fires. Fortunately, this step is very easy and handled inside of the appDelegate. When a notification fires, there are one of two situations. 1. The app is running and 2. The app is not running (or running in the “background”) .
8. Open up your app delegate .m file and add the following code.
application.applicationIconBadgeNumber = 0;
UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotif) {
NSLog(@”Recieved Notification %@”,localNotif);
}
The first thing we see here is the application badge number is getting set to 0. Whenever a notification fires, it will increase the badge count on the application. Next, we handle the case when the application launches from a notification. This happens when the user presses the view button on the notification. For now, we just NSLog the data, but you should handle the notification how you see fit for your app.
Finally, we implement the didReceiveLocalNotification method. This method is required if you want to handle notifications at all in your app. You will see this method fire when the app is running and you receive a local notification. When the app is running, you will not see the UIAlertView show up with the notification data.
We should be done now. Giver ‘er a run and see what happens! You should see something similar to this:
And there you have it! The complete lifecycle of a local notification. You may download the source for this tutorial below. If you have any questions, feel free to post them in the comments section. Also, if you felt this tutorial was too hard for you let me know, but if you felt it was just fine then I will continue to do tutorials with a higher complexity, such as this one.