It seems that
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
and
didReceiveLocalNotification:(UILocalNotification *)notification
are only triggered if the user acknowledges the UILocalNotification, for example by swiping the slider or touching the entry in iOS's Notification pull-down.
Is there any way to tell that a UILocalNotification has gone off if the user ignores the UILocalNotification and re-enters the app by simply clicking on the app icon?
I should mention that this really only applies to repeating notifications because the firing of non-repeating notifications can be detected by observing the total count. That is, when they fire, the vanish from [[UIApplication sharedApplication] scheduledLocalNotifications].
I'm looking for something like..
[[UIApplication sharedApplication] unacknowledgedLocalNotifications]
Alas, I can't find anything like it.
Well, you can check your scheduled notifications inside [[UIApplication sharedApplication] scheduledLocalNotifications]. To find out if a scheduled repeating notification has fired access the fireDate property to see what was the initial date set for the notification. Then check the repeatInterval property.
So there you have 2 variables, one is the initial NSDate, lets say 2013-05-08 12:00 and second is the repeat interval, lets say daily. And by doing a [NSDate date] you will get the current date which where I'm located (in Sweden) is now 2013-05-09 22:45. So this means that there is one notification the user has not acted on.
So you will need to create a method that will take these arguments and then iterate from the initial date to see how many notifications that have been missed until the current datetime.
You will find NSCalendars dateByAddingComponents:toDate:options useful.
Everyone has likely since moved on, but I'd like to share my solution to this problem. (Sorry about the long variables names...)
The idea is simple: always keep the fireDate in the future.
-every time didFinishLaunchingWithOptions or didReceiveLocalNotification is invoked, simply cancel your current notification and reschedule a new one with a fireDate one interval unit in the future
-When your app launches iterate through all scheduled notifications, if the fireDate is not in the future you know that it was ignored
In my case, the notifications have a weekly repeat interval. I first reschedule any acknowledged notifications in didFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UILocalNotification* localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotif != nil)
{
[NotificationsHelper rescheduleNotification:localNotif];
}
}
And also in didReceiveLocalNotification:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *) notification
{
[NotificationsHelper rescheduleNotification:notification];
}
At App Launch I check all notifications for any with a fireDate in the past:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[self checkLocalNotifications:application];
}
Code for my "checkLocalNotifications" function:
- (void) checkLocalNotifications:(UIApplication *) application
{
UIApplication* app = [UIApplication sharedApplication];
NSArray* eventArray = [app scheduledLocalNotifications];
for (int i = 0; i < [eventArray count]; i++)
{
UILocalNotification* notification = [eventArray objectAtIndex:i];
if ([NotificationsHelper wasWeeklyRepeatingNotificationIgnored:notification])
{
[NotificationsHelper rescheduleNotification:notification];
NSLog(@"NotificationWasIgnored: %@ %@",notification.alertAction, notification.alertBody );
}
}
}
Code for my "wasWeeklyRepeatingNotificationIgnored" function:
+ (BOOL) wasWeeklyRepeatingNotificationIgnored:(UILocalNotification*) the_notification
{
BOOL result;
NSDate* now = [NSDate date];
// FireDate is earlier than now
if ([the_notification.fireDate compare:now] == NSOrderedAscending)
{
result = TRUE;
}
else
{
result = FALSE;
}
return result;
}
Code for my "rescheduleNotification" function:
+ (void) rescheduleNotification:(UILocalNotification*) the_notification
{
UILocalNotification* new_notification = [[UILocalNotification alloc] init];
NSMutableDictionary* userinfo = [[NSMutableDictionary alloc] init];
[new_notification setUserInfo:userinfo];
[new_notification setRepeatInterval:the_notification.repeatInterval];
[new_notification setSoundName:UILocalNotificationDefaultSoundName];
[new_notification setTimeZone:[NSTimeZone defaultTimeZone]];
[new_notification setAlertAction:the_notification.alertAction];
[new_notification setAlertBody:the_notification.alertBody];
[new_notification setRepeatCalendar:[NSCalendar currentCalendar]];
[new_notification setApplicationIconBadgeNumber:the_notification.applicationIconBadgeNumber];
NSCalendar* gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents* weekdayComponents = [gregorian components:NSWeekdayCalendarUnit
fromDate:the_notification.fireDate];
NSInteger weekday = [weekdayComponents weekday];
NSDate* next_week = [self addDay:weekday toHourMinute:the_notification.fireDate];
[new_notification setFireDate:next_week];
[[UIApplication sharedApplication] scheduleLocalNotification:new_notification];
[[UIApplication sharedApplication] cancelLocalNotification:the_notification];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With