Comment saisir la date d'incendie PROCHAINE d'un objet UILocalNotification
-
29-09-2019 - |
Question
J'ai un objet UILocalNotification que j'ai installé avec des intervalles réguliers jour, semaine et mois. J'ai aucun problème du tout accès à la date d'incendie de l'objet:
[cell.detailTextLabel setText:[notification1.fireDate description]];
Mais j'ai des problèmes à obtenir la prochaine date d'incendie. Si j'imprimer l'objet notification1 ci-dessus à la console, je reçois ceci:
<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}
Cet objet contient quelque part la valeur ou les données dont j'ai besoin pour afficher la prochaine date de feu ... mais je ne peux pas le trouver! Est-ce que quelqu'un sait où je peux l'obtenir par programmation?
Merci
La solution
Je ne pense pas que la prochaine date d'incendie est disponible comme une propriété mais plutôt calculée à partir fireDate
et repeatInterval
. calcul de la date peut être difficile avec les différents fuseaux horaires et autres choses désagréables. Dans votre exemple, vous avez choisi une répétition quotidienne et de calculer la prochaine date de feu, vous pouvez faire quelque chose le long des lignes de:
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];
Si vous utilisez une autre répétition d'intervalle vous devez modifier le code en conséquence. Si vous deviez utiliser NSMonthCalendarUnit
vous devez utiliser components.month = 1
à la place.
Autres conseils
Pour calculer le suivant Date de feu pour un UILocalNotification
répéter, vous devez:
- Figure le montant de
repeatInterval
il y a eu entre la date d'incendie d'origine de la notification (à savoir sa propriété defireDate
) et maintenant. - les Ajouter au
fireDate
de la notification.
Voici une approche:
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];
Cela fonctionne dans de nombreux scénarios, mais voici un scénario où il ne fonctionnera pas:
Supposons que:
- `fireDate est de la notification 01/01 à 14h00
- est
repeatInterval
(à savoir la répétition quotidienne) deNSDayCalendaryUnit
de la notification - La date est maintenant à 08/01 15h00
Le code ci-dessus calcule la différence de 7 jours (01/01 + 7 jours = 08/01), les ajouter à fireDate
, et donc ensemble nextFireDate
08/01 à 14 heures . Mais ce qui est du passé, nous voulons nextFireDate
être 09/01 à 14 heures !
Donc si vous utilisez le code ci-dessus et votre repeatInterval
est NSDayCalendaryUnit
, puis ajoutez ces lignes:
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];
}
J'ont pensé que cet wiki de la communauté, ne hésitez pas à modifier si vous avez trouvé une meilleure façon de faire le calcul!
Je voudrais simplement ajouter repeatInterval jusqu'à ce que les mensonges de date dans l'avenir:
-(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;
}
est Swift 4 et en utilisant func nextDate
du calendrier.
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)
}
}