Can't schedule daily local PushNotification
in correct way.
I want to show only one daily local PushNotification at 9:00 AM with counted tasks for today.
My code executed only once in didFinishLaunchingWithOptions
like:
- (void)scheduleLocalNotification
{
self.localNotification = [UILocalNotification new];
unsigned unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:unitFlags fromDate:[NSDate date]];
components.hour = 9;
components.minute = 0;
components.second = 0;
NSDate *fireTime = [calendar dateFromComponents:components];
_localNotification.fireDate = fireTime;
_localNotification.alertBody = [NSString stringWithFormat:@"Hi, <username>. You have %ld tasks for today", (long)_todayTasks];
_localNotification.repeatInterval = NSCalendarUnitDay;
_localNotification.soundName = @"alarm.wav";
_localNotification.timeZone = [NSTimeZone localTimeZone];
[[UIApplication sharedApplication] scheduleLocalNotification:_localNotification];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"HH:mm"];
NotificationManagerLog(@"schedule local notification at %@", [dateFormatter stringFromDate:fireTime]);
}
Looks like I miss something, because it's really triggered at 9:00, but with wrong data in _todayTasks
, also it can be randomly triggered with other _todayTasks
values and repeated few times at random time.
Step by step:
Register notifications:
- (void)prepareLocalNotification
{
if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
} else {
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes];
}
}
Create notification if user allow local Notifications (example 3pm every day):
- (void)createDailyBasisNotification
{
[[UIApplication sharedApplication] cancelAllLocalNotifications];
UILocalNotification *next3pm = [self notificationForTime:15 withMessage:<NotificationMessage3PM> soundName:UILocalNotificationDefaultSoundName];
[[UIApplication sharedApplication] scheduleLocalNotification:next3pm];
}
- (UILocalNotification *)notificationForTime:(NSInteger)time withMessage:(NSString *)message soundName:(NSString *)soundName
{
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertBody = message;
localNotification.repeatInterval = NSDayCalendarUnit;
localNotification.timeZone = [NSTimeZone localTimeZone];
localNotification.soundName = soundName;
NSDate *date = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponents = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:date];
[dateComponents setHour:time];
NSDate *next = [calendar dateFromComponents:dateComponents];
if ([next timeIntervalSinceNow] < 0) {
next = [next dateByAddingTimeInterval:60*60*24];
}
localNotification.fireDate = next;
return localNotification;
}
Also don't forget to call [[UIApplication sharedApplication] cancelAllLocalNotifications];
- this will clean up all notification and u will remove all random
notifications
Can't see where you're defining _todayTasks
.
Your code for triggering the notification in general should work. And like you said, it does.
Maybe _todayTasks
hasn't been initialized yet (at startup)? Are you using NSUserDefaults?
Another problem could be that you haven't cleared you're old notifications which have been scheduled by multiple launches and therefore the data is wrong?
You could try NSLog to print the data and look whats inside first.
I schedule my notification when the "applicationWillResignActive
" method is called.
Also I clear all other notification when the app launches again ("applicationDidBecomeActive
") like this (unfortunately in swift):
// Clear all Notifications
let notifications = UIApplication.sharedApplication().scheduledLocalNotifications!
if notifications.count > 0 {
print("reset Notifications.")
UIApplication.sharedApplication().cancelAllLocalNotifications()
}
NSString *strCurrentDate = [dateformat stringFromDate:[NSDate date]];
if ([strCurrentDate isEqualToString:[AppData getAppData].strLastDate])
{
[[AppData getAppData] setIsDoneLN:YES];
}
else
{
[[AppData getAppData] setIsDoneLN:NO];
}
if (![AppData getAppData].isDoneLN) {
[self callLN];
}
-(void)callLN
{
// your notification code here
NSDateFormatter *dateformat;
if (!dateformat)
{
dateformat = [[NSDateFormatter alloc] init];
}
[dateformat setDateFormat:@"yyyy-MM-dd"];
[[AppData getAppData] setStrLastDate:[dateformat stringFromDate:[NSDate date]]];
}
//NOTE:[AppData getAppData] is a singleton class that return NSUserDefaults value. you can use normal NSUserDefaults to save and retrive the values instead of using [AppData getAppData].