How to schedule daily local push notification in i

2019-03-04 13:03发布

问题:

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.

回答1:

Step by step:

  1. 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];
        }
    }
    
  2. 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



回答2:

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()
}


回答3:

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].