如何从 UILocalNotification 对象获取下一个触发日期

发布于 2024-10-05 10:29:23 字数 531 浏览 6 评论 0原文

我有一个 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}

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

谢谢

I have a UILocalNotification object that I have setup with repeat intervals day, week, and month. I am having no troubles at all accessing the fire date of the object:

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

But I am having troubles getting the next fire date. If I print out the above notification1 object to the console, I get this:

<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}

This object contains somewhere the value or data I need to display the next fire date...but I can't find it! Does anybody know where I can get it programmatically?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

白况 2024-10-12 10:29:23

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

  1. 计算出通知原始触发日期之间的 repeatInterval 时间(即它的 fireDate 属性)和现在。
  2. 将它们添加到通知的 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 点。但那已经是过去的事了,我们希望 nextFireDate09/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,如果您找到了更好的答案,请随时编辑它计算方法!

To calculate the next fire date for a repeating UILocalNotification, you have to:

  1. Figure out the amount of repeatInterval there's been between the notification's original fire date (i.e. its fireDate property) and now.
  2. Add them to the notification's fireDate.

Here's one approach:

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];

This works in many scenarios, but here's a scenario where it won't work:

Suppose that:

  • the notification's `fireDate is 01/01 at 2:00pm
  • the notification's repeatInterval is NSDayCalendaryUnit (i.e. repeat daily)
  • The date now is 08/01 at 3:00pm

The above code will calculate the difference to 7 days (01/01 + 7 days = 08/01), add them to fireDate, and thus set nextFireDate to 08/01 at 2pm. But that's in the past, we want nextFireDate to be 09/01 at 2pm!

So if using the above code and your repeatInterval is NSDayCalendaryUnit, then add these lines:

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];
}

I marked this answer as community wiki, feel free to edit it if you have found a better way to do the calculation!

离旧人 2024-10-12 10:29:23

我认为下一个触发日期不能作为属性使用,而是根据 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

I don't think the next fire date is available as a property but rather calculated from fireDate and repeatInterval. Date calculating can be tricky with different time zones and other nasty things. In your example you have chosen a daily repeat and to calculate the next fire date you can do something along the lines of:

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];

If you use some other repeat interval you would have to change the code accordingly. If you were to use NSMonthCalendarUnit you would have to use components.month = 1 instead.

涫野音 2024-10-12 10:29:23

我只需添加重复间隔,直到未来的日期:

-(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;
    }

i would just add the repeatInterval until the date lies in the future:

-(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;
    }
风渺 2024-10-12 10:29:23

这是在 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)
    }

}

This is in Swift 4 and using calendar's nextDate func.

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)
    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文