如何在 iOS (ObjC) 中安排每日本地推送通知?

How to schedule daily local push notification in iOS (ObjC)?

无法以正确的方式安排每日本地 PushNotification。 我只想在 9:00 AM 显示一个每日本地 PushNotification,其中包含今天的计数任务。

我的代码在 didFinishLaunchingWithOptions 中只执行了一次,例如:

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

看来我漏掉了什么,因为它确实在 9:00 触发,但在 _todayTasks 中有错误的数据,也可以用其他 _todayTasks 值随机触发并重复几次随机时间的次数。

一步一步:

  1. 注册通知:

    - (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. 如果用户允许本地通知(例如每天下午 3 点),则创建通知:

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

另外不要忘记调用 [[UIApplication sharedApplication] cancelAllLocalNotifications]; - 这将清除所有通知,您将删除所有 random 通知

看不到您定义的位置 _todayTasks。 您用于触发通知的代码通常应该可以工作。正如你所说,确实如此。

可能 _todayTasks 还没有初始化(启动时)?你在使用 NSUserDefaults 吗?

另一个问题可能是你没有清除你的旧通知,这些通知已被多次启动安排,因此数据错误?

你可以试试NSLog打印数据,先看看里面是什么。

我在调用“applicationWillResignActive”方法时安排通知。 当应用程序再次启动时,我也会清除所有其他通知(“applicationDidBecomeActive”),就像这样(不幸的是在 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].