Wie das nächste Feuer Datum aus einem UILocalNotification Objekt greifen
-
29-09-2019 - |
Frage
ich ein UILocalNotification bezweckt, dass ich Setup mit Wiederholungsintervallen Tag, Woche und Monat. Ich habe keine Probleme überhaupt das Feuer Datum des Objekts zugreifen:
[cell.detailTextLabel setText:[notification1.fireDate description]];
Aber ich habe Probleme das nächste Feuer Datum bekommen. Wenn ich das oben notification1 Objekt auf die Konsole ausdrucken, ich diese:
<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}
Dieses Objekt enthält irgendwo den Wert oder die Daten Ich brauche das nächste Feuer Datum anzuzeigen ... aber ich kann es nicht finden! Weiß jemand, wo ich kann es programmatisch bekommen?
Danke
Lösung
Ich glaube nicht, das nächste Feuer Datum als Objekt vorhanden ist, sondern von fireDate
und repeatInterval
berechnet. Datum Berechnung kann mit verschiedenen Zeitzonen und anderen unangenehmen Dingen schwierig sein. In Ihrem Beispiel haben Sie eine tägliche Wiederholung ausgewählt und das nächste Feuer Datum berechnen Sie etwas entlang der Linien von tun können:
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];
Wenn Sie eine andere Wiederholung verwenden Intervall Sie den Code entsprechend ändern müssten. Wenn Sie NSMonthCalendarUnit
verwenden wären, würden Sie components.month = 1
stattdessen verwenden.
Andere Tipps
Um das Weiter Feuer Datum für eine Wiederholung UILocalNotification
zu berechnen, müssen Sie:
- Herauszufinden, die Menge an
repeatInterval
Es gab zwischen der ursprünglichen Feuer Datum der Mitteilung (das heißt seinefireDate
Eigenschaft) und jetzt. - Fügen sie die Mitteilung des
fireDate
.
Hier ist ein Ansatz:
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];
Dies funktioniert in vielen Szenarien, aber hier ist ein Szenario, in dem es wird nicht funktionieren:
Nehmen wir an, dass:
- die Mitteilung der `fireDate ist 01/01 um 14.00 Uhr
- die Mitteilung des
repeatInterval
istNSDayCalendaryUnit
(d wiederholen täglich) - Das Datum ist jetzt 01.08 um 15.00 Uhr
Der obige Code wird den Unterschied zu 7 Tagen (01/01 + 7 Tage = 08/01), fügen Sie sich fireDate
und damit Satz nextFireDate
auf 01.08 auf 14.00 Uhr berechnen. Aber das ist in der Vergangenheit, wir wollen nextFireDate
sein 01.09 auf 14.00 Uhr !
Also, wenn Sie den obigen Code verwenden und Ihre repeatInterval
ist NSDayCalendaryUnit
, dann fügen Sie die folgenden Zeilen:
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];
}
Ich markierte diese Antwort als Community Wiki, es fühlen Sie sich frei zu bearbeiten, wenn Sie einen besseren Weg gefunden haben, um die Berechnung zu tun!
ich würde nur die repeatInterval bis das Datum liegt in der Zukunft hinzuzufügen:
-(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;
}
Dies ist in Swift 4 und mit Kalender des 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)
}
}