如何从 UILocalNotification 对象中获取 NEXT 触发日期

Posted

技术标签:

【中文标题】如何从 UILocalNotification 对象中获取 NEXT 触发日期【英文标题】:How to grab the NEXT fire date from a UILocalNotification object 【发布时间】:2010-11-29 05:54:12 【问题描述】:

我有一个 UILocalNotification 对象,我设置了重复间隔日、周和月。我在访问对象的触发日期时完全没有问题:

[cell.detailTextLabel setText:[notification1.fireDate description]];

但是我在确定下一个开火日期时遇到了麻烦。如果我将上述 notification1 对象打印到控制台,我会得到:

<UIConcreteLocalNotification: 0x613e060>fire date = 2010-11-29 03:53:52 GMT, time zone = America/Denver (MST) offset -25200, repeat interval = 16, next fire date = 2010-11-30 03:53:52 GMT

这个对象在某处包含我需要显示下一个开火日期的值或数据......但我找不到它!有人知道我可以在哪里以编程方式获得它吗?

谢谢

【问题讨论】:

***.com/questions/3984911/…的副本 好吧,我在问了我的问题后看到了,但没有答案……那我该怎么办? 对象明明知道下一次开火日期是什么时候却没有暴露给你,这很令人沮丧。 【参考方案1】:

要计算重复UILocalNotification下一个触发日期,您必须:

    算出通知的原始触发日期(即其fireDate 属性)与现在之间的repeatInterval 数量。 将它们添加到通知的fireDate

这是一种方法:

NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];

NSDateComponents *difference = [calendar components:notif.repeatInterval
                                           fromDate:notif.fireDate
                                             toDate:[NSDate date]
                                            options:0];

NSDate *nextFireDate = [calendar dateByAddingComponents:difference
                                                 toDate:notif.fireDate
                                                options:0];

这在许多情况下都有效,但在以下情况下它不起作用:

假设:

通知的 `fireDate 是 01/01 下午 2:00 通知的repeatIntervalNSDayCalendaryUnit(即每天重复) 现在的日期是 08/01 下午 3:00

上面的代码会计算到 7 天的差值(01/01 + 7 天 = 08/01),将它们添加到 fireDate,从而将 nextFireDate 设置为 08/01 下午 2 点强>。但那已经是过去了,我们希望 nextFireDate 成为 09/01 下午 2 点

所以如果使用上面的代码并且你的repeatIntervalNSDayCalendaryUnit,那么添加这些行:

if ([nextFireDate timeIntervalSinceDate:[NSDate date]] < 0) 
    //next fire date should be tomorrow!
    NSDateComponents *extraDay = [[NSDateComponents alloc] init];
    extraDay.day = 1;
    nextFireDate = [calendar dateByAddingComponents:extraDay toDate:nextFireDate options:0];

我将此答案标记为社区 wiki,如果您找到了更好的计算方法,请随时编辑它!

【讨论】:

我们可以跳过即将到来的开火日期,而不是处理下一个开火日期吗?并在下一个重复时间继续 这几乎是但不完全 - 看似正确的答案在这里:***.com/questions/20926952/…【参考方案2】:

我不认为下一个开火日期可作为财产使用,而是根据fireDaterepeatInterval 计算得出。对于不同的时区和其他讨厌的事情,日期计算可能会很棘手。在您的示例中,您选择了每天重复一次,并且要计算下一个触发日期,您可以按照以下方式进行操作:

NSCalendar *calendar = localNotif.repeatCalendar;
if (!calendar) 
  calendar = [NSCalendar currentCalendar];


NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease];
components.day = 1;
NSDate *nextFireDate = [calendar dateByAddingComponents:components toDate:localnotif.fireDate options:0];

如果您使用其他重复间隔,则必须相应地更改代码。如果您要使用NSMonthCalendarUnit,则必须改用components.month = 1

【讨论】:

嘿,非常感谢!我想我现在肯定有一个坚定的方向 这不是一个正确的答案。这只是将一个组件元素添加到通知初始触发日期,它不计算重复通知的发生次数。 为了阻止任何未来的相同性质的编辑建议,请勿编辑此帖子以说它不正确,并插入指向更正确答案的链接。相反,对帖子进行投票并在必要时留下 cmets。 @FabrizioProsperi,我看不到提问者在哪里谈论计算通知发生次数。对我来说,这绝对是一个很好且正确的答案。 @FabrizioProsperi,好的,我明白你的意思。但对我来说,这 一个很好的答案,因为它肯定会在解决方案的轨道上。好的,这不会“按原样”工作,但稍加思考,我们可以轻松地根据他的答案编写算法。 *** 不应该是我们只是将代码复制粘贴到生产应用程序的地方。【参考方案3】:

我只会添加repeatInterval,直到日期在未来:

-(NSDate*)nextFireDateForNotification:(UILocalNotification*)notification 
        NSCalendar *calendar = notification.repeatCalendar;
        if (!calendar) 
            calendar = [NSCalendar currentCalendar];
        

        NSDate* date = [notification.fireDate copy];
        while (date.timeIntervalSinceNow > 0) 
            date = [calendar dateByAddingUnit:notification.repeatInterval value:1 toDate:date options:0];
        
        return date;
    

【讨论】:

【参考方案4】:

这是在 Swift 4 中并使用日历的 nextDate 函数。

extension UILocalNotification 

    var nextFireDate: Date? 
        guard let fireDate = fireDate else  return nil 

        let today = Date()
        let cal = Calendar.current

        if fireDate.compare(today) == .orderedDescending 
            return fireDate
        

        let s: Set<Calendar.Component>
        switch repeatInterval 
        case .year: s = [.month, .day, .hour, .minute, .second]
        case .month: s = [.day, .hour, .minute, .second]
        case .day: s = [.hour, .minute, .second]
        case .hour: s = [.minute, .second]
        case .minute: s = [.second]
        default: return nil // Not supporting other intervals
        

        let components = cal.dateComponents(s, from: fireDate)
        return cal.nextDate(after: today, matching: components, matchingPolicy: .nextTimePreservingSmallerComponents)
    


【讨论】:

以上是关于如何从 UILocalNotification 对象中获取 NEXT 触发日期的主要内容,如果未能解决你的问题,请参考以下文章

如何从自定义类创建和取消唯一的 UILocalNotification?

从 iPad 删除应用程序时如何删除 UILocalNotification applicationIconBadgeNumber?

从 UILocalNotification 打开应用程序时转到视图控制器

从 iphone 中的可用声音为 UILocalNotification 分配警报音

从 UILocalNotification 呈现视图控制器的问题

如何检查被忽略的 UILocalNotification?