Как получить СЛЕДУЮЩУЮ дату пожара из объекта UILocalNotification - PullRequest
4 голосов
/ 29 ноября 2010

У меня есть объект 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}

Этот объект содержит где-то значение или данные, которые мне нужны для отображения даты следующего пожара ... но я не могу его найти! Кто-нибудь знает, где я могу получить это программно?

Спасибо

Ответы [ 4 ]

9 голосов
/ 11 сентября 2013

Чтобы вычислить следующую дату срабатывания для повторяющегося 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 pm
  • в уведомлении repeatInterval указано NSDayCalendaryUnit (то есть повторяется ежедневно)
  • Дата теперь 08/01 в 15:00

Приведенный выше код рассчитает разницу до7 дней (01/01 + 7 дней = 08/01), добавьте их к fireDate и, таким образом, установите nextFireDate на 08/01 в 14:00 .Но это в прошлом, мы хотим, чтобы nextFireDate было 09/01 в 14:00 !

Итак, если вы используете приведенный выше код и ваш repeatInterval равен NSDayCalendaryUnit, добавьте следующие строки:

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

Я отметил этот ответ как вики сообщества, не стесняйтесь редактировать его, еслиВы нашли лучший способ сделать расчет!

7 голосов
/ 29 ноября 2010

Я не думаю, что следующая дата пожара доступна как собственность, но скорее рассчитывается из fireDate и repeatInterval.Расчет даты может быть сложным с различными часовыми поясами и другими неприятными вещами.В вашем примере вы выбрали ежедневное повторение, и для вычисления следующей даты срабатывания вы можете сделать что-то вроде:

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.

0 голосов
/ 15 августа 2018

Это в Swift 4 и используется календарь 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)
    }

}
0 голосов
/ 04 ноября 2016

Я бы просто добавил 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;
    }
...