【问题标题】:Detect next UILocalNotification that will fire检测下一个将触发的 UILocalNotification
【发布时间】:2014-01-04 21:25:46
【问题描述】:

有没有办法找到NSDate 以获取下一个将触发的本地通知?

例如,我设置了三个本地通知:

通知 #1:设置为昨天下午 3:00 触发,每天重复一次。

通知 #2:设置为今天下午 5:00 触发,每天重复一次。

通知 #3:设置为明天下午 6:00 触发,每天重复一次。

鉴于当前是下午 4:00,下一个将触发的本地通知是通知 #2。

如何检索此本地通知并获取其日期?

我知道我可以在数组中检索这些本地通知,但是如何获取下一个将根据今天的日期触发的通知?

【问题讨论】:

    标签: ios cocoa-touch nsarray uilocalnotification


    【解决方案1】:

    您的任务的主要目标是确定给定时间之后的“下一个开火日期” 每个通知的日期。 UILocalNotificationNSLog() 输出显示下一个触发日期, 但不幸的是,它似乎不能作为(公共)财产使用。

    我已从https://stackoverflow.com/a/18730449/1187415 获取代码(带有小 改进)并将其重写为UILocalNotification 的类别方法。 (这并不完美。它不包括 时区 分配给通知。)

    @interface UILocalNotification (MyNextFireDate)
    - (NSDate *)myNextFireDateAfterDate:(NSDate *)afterDate;
    @end
    
    @implementation UILocalNotification (MyNextFireDate)
    - (NSDate *)myNextFireDateAfterDate:(NSDate *)afterDate
    {
        // Check if fire date is in the future:
        if ([self.fireDate compare:afterDate] == NSOrderedDescending)
            return self.fireDate;
    
        // The notification can have its own calendar, but the default is the current calendar:
        NSCalendar *cal = self.repeatCalendar;
        if (cal == nil)
            cal = [NSCalendar currentCalendar];
    
        // Number of repeat intervals between fire date and the reference date:
        NSDateComponents *difference = [cal components:self.repeatInterval
                                                   fromDate:self.fireDate
                                                     toDate:afterDate
                                                    options:0];
    
        // Add this number of repeat intervals to the initial fire date:
        NSDate *nextFireDate = [cal dateByAddingComponents:difference
                                                         toDate:self.fireDate
                                                        options:0];
    
        // If necessary, add one more:
        if ([nextFireDate compare:afterDate] == NSOrderedAscending) {
            switch (self.repeatInterval) {
                case NSDayCalendarUnit:
                    difference.day++;
                    break;
                case NSHourCalendarUnit:
                    difference.hour++;
                    break;
                // ... add cases for other repeat intervals ...
                default:
                    break;
            }
            nextFireDate = [cal dateByAddingComponents:difference
                                                toDate:self.fireDate
                                               options:0];
        }
        return nextFireDate;
    }
    @end
    

    使用它,您可以根据 下次开火日期:

    NSArray *notifications = @[notif1, notif2, notif3];
    
    NSDate *now = [NSDate date];
    NSArray *sorted = [notifications sortedArrayUsingComparator:^NSComparisonResult(UILocalNotification *obj1, UILocalNotification *obj2) {
        NSDate *next1 = [obj1 myNextFireDateAfterDate:now];
        NSDate *next2 = [obj2 myNextFireDateAfterDate:now];
        return [next1 compare:next2];
    }];
    

    现在sorted[0] 将是下一个触发的通知。

    【讨论】:

    • 非常感谢您的详细回复!
    • 很棒的答案,至少值得+2!当您复制并粘贴此代码时,请注意 switch 语句,因为您可能需要在此处添加一些额外的代码:)
    • @MartinR 您能否根据 [NSTimeZone defaultTimeZone] 更新您的代码,也请查看此问题stackoverflow.com/questions/38199944/…
    • 请更新这个很棒的代码以覆盖时区。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多