Cómo agarrar la fecha de fuego SIGUIENTE de un objeto UILocalNotification
-
29-09-2019 - |
Pregunta
tengo un objeto UILocalNotification que he fijado con intervalos de repetición días, semanas y meses. Estoy teniendo ningún problema en absoluto el acceso a la fecha de fuego del objeto:
[cell.detailTextLabel setText:[notification1.fireDate description]];
Pero estoy teniendo problema para conseguir la próxima fecha de fuego. Si imprimo el objeto notification1 anterior a la consola, me sale esto:
<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}
Este objeto contiene algún lugar del valor o datos que necesito para mostrar la siguiente fecha de fuego ... pero no puedo encontrar! ¿Alguien sabe donde puedo conseguirlo mediante programación?
Gracias
Solución
No creo que la próxima fecha de fuego está disponible como una propiedad sino más bien calculada a partir de fireDate
y repeatInterval
. Fecha de cálculo puede ser complicado con diferentes zonas horarias y otras cosas desagradables. En su ejemplo se ha elegido una repetición diaria y para calcular la próxima fecha de fuego que puede hacer algo en la línea 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 utilizar algún otro intervalo de repetición que tendría que cambiar el código en consecuencia. Si se va a utilizar NSMonthCalendarUnit
tendría que utilizar components.month = 1
lugar.
Otros consejos
Para calcular la Siguiente fecha de fuego durante un UILocalNotification
repetir, usted tiene que:
- Averiguar la cantidad de
repeatInterval
que ha habido entre la fecha de fuego original de la notificación (es decir, su propiedadfireDate
) y ahora. - Añadir a
fireDate
de la notificación.
Aquí está uno de los enfoques:
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];
Esto funciona de muchos escenarios, pero aquí hay un escenario en el que no va a funcionar:
Supongamos que:
- de la notificación `fireDate es 01/01 a las 2:00 pm
-
repeatInterval
de la notificación esNSDayCalendaryUnit
(es decir, la repetición diaria) - La fecha actual es 08/01 a las 3:00 pm
El código anterior calcular la diferencia a 7 días (01/01 + 7 días = 08/01), añadirlos a fireDate
, y por lo tanto conjunto nextFireDate
a 08/01 a 14:00 . Pero eso está en el pasado, queremos nextFireDate
sea 09/01 a las 14:00 !
Así que si se utiliza el código anterior y su repeatInterval
es NSDayCalendaryUnit
, a continuación, añadir estas líneas:
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];
}
Esta respuesta ha resultado wiki de la comunidad, no dude en editar si usted ha encontrado una mejor manera de hacer el cálculo!
i simplemente añadiría la repeatInterval hasta que la fecha está en el futuro:
-(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;
}
Este es en Swift 4 y el uso de nextDate
func de calendario.
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)
}
}