ios - 如何每天不同时间重复本地通知

标签 ios objective-c uilocalnotification

我正在开发一个祈祷应用程序,该应用程序使用户能够为祈祷时间设置警报(本地通知),即用户将应用程序设置为每天通知他进行 Fajr 祈祷,问题是每次祈祷的时间每天都在变化,所以应用程序通知用户的时间在星期四与星期五的时间会有所不同,我需要每天重复本地通知,但根据每天的祈祷时间,请问有人能给我一个主意吗?

最佳答案

对此有几种可能的解决方案。使用一次安排有限数量通知的方法可能更安全,因为 iOS 只保留 64 个最快的通知:

An app can have only a limited number of scheduled notifications; the system keeps the soonest-firing 64 notifications (with automatically rescheduled notifications counting as a single notification) and discards the rest.

来源:UILocalNotification 类引用

依赖于使用传递给 application:didFinishLaunchingWithOptions:UILocalNotification 也不是一个好主意,因为它仅在用户滑动通知时传递:

Look at the launch options dictionary to determine why your app was launched. The application:willFinishLaunchingWithOptions: and application:didFinishLaunchingWithOptions: methods provide a dictionary with keys indicating the reason that your app was launched.

启动以响应本地通知的关键值是: UIApplicationLaunchOptionsLocalNotificationKey

来源:UIApplicationDelegate 类引用

选项 1:一次安排一天(下面提供了此代码)

处理通知安排的一种方法是向用户提供一个时间表,其中当天的通知安排在应用程序首次打开时。

使用 CustomNotificationManager 类来处理时间可变的通知(下面提供的代码)。在您的 AppDelegate 中,您可以将本地通知的处理委托(delegate)给此类,它将安排当天的通知加上第二天的固定时间通知,或者响应祈祷通知。

如果用户打开应用程序以响应祈祷通知,应用程序可以将用户引导至应用程序的适当部分。如果用户打开应用响应定时通知,应用将根据用户的日期和位置安排当天的本地通知。

选项 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。

关于ios - 如何每天不同时间重复本地通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25700890/

相关文章:

ios - Swift 中的服务定位器模式

iphone - 在 iPhone 上使用 AudioQueue 录制/播放

ios - 安排交互式 UILocalNotification - Obj-C

ios - 为什么我的 Tableview 数据是空白的?我无法重新加载数据

xcode - 在 Swift 中发送带有日期的本地推送通知AddingTimeInterval

iphone - 当应用程序处于后台时,不在应用程序委托(delegate)中调用 didReceiveLocalNotification 方法 [iOS6]

ios - iOS 11 中的应用内推广问题

ios - 在 iOS 中创建另一个 View 的图像

ios - 如何检查 UIButton 是否被按住?

objective-c - UILocalNotification 立即触发,而不是在预定时间触发