如何在 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
值随机触发并重复几次随机时间的次数。
一步一步:
注册通知:
- (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];
}
}
如果用户允许本地通知(例如每天下午 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].
无法以正确的方式安排每日本地 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
值随机触发并重复几次随机时间的次数。
一步一步:
注册通知:
- (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]; } }
如果用户允许本地通知(例如每天下午 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].