对此有几种可能的解决方案。使用一次安排有限数量的通知的方法可能更安全,因为 iOS 只保留 64 个最快的通知:
一个应用只能有有限数量的预定通知;系统保留最快触发的 64 条通知(自动重新安排的通知计为单个通知)并丢弃其余通知。
来源:UILocalNotification 类参考
依赖使用传递给application:didFinishLaunchingWithOptions: 的UILocalNotification 也不是一个好主意,因为它仅在用户滑动通知时传递:
查看启动选项字典以确定您的应用启动的原因。 application:willFinishLaunchingWithOptions: 和 application:didFinishLaunchingWithOptions: 方法提供了一个字典,其中的键指示您的应用启动的原因。
响应本地通知启动的关键值为:
UIApplicationLaunchOptionsLocalNotificationKey
来源:UIApplicationDelegate 类参考
选项 1:一次安排一天(代码如下)
处理通知安排的一种方法是向用户显示一个安排,其中当天的通知安排在应用程序首次打开时安排。
使用CustomNotificationManager 类来处理时间可变的通知(下面提供的代码)。在您的 AppDelegate 中,您可以将本地通知的处理委托给此类,这将安排当天的通知和第二天的固定时间通知,或者响应祈祷通知。
如果用户打开应用程序以响应祈祷通知,应用程序可以将用户引导至应用程序的适当部分。如果用户打开应用响应定时通知,应用会根据用户的日期和位置安排当天的本地通知。
选项 2(略微精简的方法,但为用户提供的内容较少)
另一种方法是简单地使用祈祷通知的应用启动来安排紧随其后的祈祷通知。但是,这不太可靠,并且不提供预览通知计划的功能。
通知管理器头文件
@interface CustomNotificationManager : NSObject
- (void) handleLocalNotification:(UILocalNotification *localNotification);
@end
通知管理器实现文件
#import "CustomNotificationManager.h"
#define CustomNotificationManager_FirstNotification @"firstNotification"
@implementation CustomNotificationManager
- (instancetype) init
{
self = [super init];
if (self) {
}
return self;
}
- (void) handleLocalNotification:(UILocalNotification *)localNotification
{
//Determine if this is the notification received at a fixed time,
// used to trigger the scheculing of today's notifications
NSDictionary *notificationDict = [localNotification userInfo];
if (notificationDict[CustomNotificationManager_FirstNotification]) {
//TODO: use custom algorithm to create notification times, using today's date and location
//Replace this line with use of algorithm
NSArray *notificationTimes = [NSArray new];
[self scheduleLocalNotifications:notificationTimes];
} else {
//Handle a prayer notification
}
}
/**
* Schedule local notifications for each time in the notificationTimes array.
*
* notificationTimes must be an array of NSTimeInterval values, set as intervalas
* since 1970.
*/
- (void) scheduleLocalNotifications:(NSArray *)notificationTimes
{
for (NSNumber *notificationTime in notificationTimes) {
//Optional: create the user info for this notification
NSDictionary *userInfo = @{};
//Create the local notification
UILocalNotification *localNotification = [self createLocalNotificationWithFireTimeInterval:notificationTime
alertAction:@"View"
alertBody:@"It is time for your next prayer."
userInfo:userInfo];
//Schedule the notification on the device
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
}
/* Schedule a notification for the following day, to come before all other notifications.
*
* This notification will trigger the app to schedule notifications, when
* the app is opened.
*/
//Set a flag in the user info, to set a flag to let the app know that it needs to schedule notifications
NSDictionary *userInfo = @{ CustomNotificationManager_FirstNotification : @1 };
NSNumber *firstNotificationTimeInterval = [self firstNotificationTimeInterval];
UILocalNotification *firstNotification = [self createLocalNotificationWithFireTimeInterval:firstNotificationTimeInterval
alertAction:@"View"
alertBody:@"View your prayer times for today."
userInfo:userInfo];
//Schedule the notification on the device
[[UIApplication sharedApplication] scheduleLocalNotification:firstNotification];
}
- (UILocalNotification *) createLocalNotificationWithFireTimeInterval:(NSNumber *)fireTimeInterval
alertAction:(NSString *)alertAction
alertBody:(NSString *)alertBody
userInfo:(NSDictionary *)userInfo
{
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
if (!localNotification) {
NSLog(@"Could not create a local notification.");
return nil;
}
//Set the delivery date and time of the notification
long long notificationTime = [fireTimeInterval longLongValue];
NSDate *notificationDate = [NSDate dateWithTimeIntervalSince1970:notificationTime];
localNotification.fireDate = notificationDate;
//Set the slider button text
localNotification.alertAction = alertAction;
//Set the alert body of the notification
localNotification.alertBody = alertBody;
//Set any userInfo, e.g. userID etc. (Useful for app with multi-user signin)
//The userInfo is read in the AppDelegate, via application:didReceiveLocalNotification:
localNotification.userInfo = userInfo;
//Set the timezone, to allow for adjustment for when the user is traveling
localNotification.timeZone = [NSTimeZone localTimeZone];
return localNotification;
}
/**
* Calculate and return a number with an NSTimeInterval for the fixed daily
* notification time.
*/
- (NSNumber *) firstNotificationTimeInterval
{
//Create a Gregorian calendar
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
//Date components for next day
NSDateComponents *dateComps = [[NSDateComponents alloc] init];
dateComps.day = 1;
//Get a date for tomorrow, same time
NSDate *today = [NSDate date];
NSDate *tomorrow = [cal dateByAddingComponents:dateComps toDate:today options:0];
//Date components for the date elements to be preserved, when we change the hour
NSDateComponents *preservedComps = [cal components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:tomorrow];
preservedComps.hour = 5;
tomorrow = [cal dateFromComponents:preservedComps];
NSTimeInterval notificationTimeInterval = [tomorrow timeIntervalSince1970];
NSNumber *notificationTimeIntervalNum = [NSNumber numberWithLongLong:notificationTimeInterval];
return notificationTimeIntervalNum;
}
@end
AppDelegate didReceiveLocalNotification 实现
- (void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
CustomNotificationManager *notificationManager = [[CustomNotificationManager alloc] init];
[notificationManager handleLocalNotification:notification];
}
可能的修改建议:如果 CustomNotificationManager 需要维护状态,您可以将其转换为 Singleton。