Как получить следующую дату пожара с объекта UilocalNotification
-
29-09-2019 - |
Вопрос
У меня есть объект UilocalNotification, который я настраиваю с повторными интервалами в день, недели и месяца. У меня нет проблем с доступом к дате пожара объекта:
[cell.detailTextLabel setText:[notification1.fireDate description]];
Но у меня возникли проблемы с получением следующей даты пожара. Если я распечатаю вышеуказанный объект уведомления1 в консоли, я получаю это:
<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}
Этот объект содержит где -то значение или данные, которые мне нужно отобразить следующую дату пожара ... но я не могу его найти! Кто -нибудь знает, где я могу получить его программно?
Спасибо
Решение
Я не думаю, что следующая дата пожара доступна как свойство, а скорее рассчитано на 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
вместо.
Другие советы
Рассчитать следующий Дата пожара для повторения UILocalNotification
, вы должны:
- Выяснить количество
repeatInterval
Там было между оригинальной датой опорожнения уведомления (т.е. ееfireDate
собственность) и теперь. - Добавить их в уведомление
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];
Это работает во многих сценариях, но вот сценарий, где он не будет работать:
Предположим, что:
- Уведомление `увольнение - 01/01 в 14:00.
- уведомление
repeatInterval
являетсяNSDayCalendaryUnit
(т.е. повторяется ежедневно) - Дата сейчас 08/01 в 15:00
Приведенный выше код рассчитал разницу до 7 дней (01/01 + 7 дней = 08/01), добавьте их в fireDate
, и, таким образом nextFireDate
к 08/01 в 2 часа дня. Анкет Но это в прошлом, мы хотим nextFireDate
быть 09/01 в 2 вечера!
Так что если использовать вышеуказанный код и ваш 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];
}
Я пометил этот ответ как Wiki, не стесняйтесь редактировать его, если вы нашли лучший способ сделать расчет!
Я бы просто добавил ReptintInderval до даты не в будущем:
-(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 и используя календарь 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)
}
}