Come afferrare la data fuoco da un oggetto AVANTI UILocalNotification
-
29-09-2019 - |
Domanda
Ho un oggetto UILocalNotification che ho installato con intervalli di ripetizione giorno, settimana e mese. Sto avendo alcun problemi a tutti l'accesso alla data di fuoco dell'oggetto:
[cell.detailTextLabel setText:[notification1.fireDate description]];
Ma io sto avendo problemi ricevendo la prossima data di fuoco. Se stampo l'oggetto notification1 sopra alla console, ottengo questo:
<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}
Questo oggetto contiene da qualche parte il valore o dati che ho bisogno per visualizzare la successiva data di fuoco ... ma non riesco a trovarlo! Qualcuno sa dove posso ottenere a livello di codice?
Grazie
Soluzione
Non credo che la prossima data di fuoco è disponibile come proprietà, ma piuttosto calcolata da fireDate
e repeatInterval
. Data di calcolo può essere difficile con diversi fusi orari e altre cose brutte. Nel tuo esempio si è scelto una ripetizione quotidiana e per calcolare la prossima data del fuoco si può fare qualcosa sulla falsariga di:
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];
Se si utilizza un altro intervallo di ripetizione si dovrebbe modificare il codice di conseguenza. Se si sceglie di usare NSMonthCalendarUnit
si dovrebbe usare components.month = 1
invece.
Altri suggerimenti
Per calcolare il Avanti data fuoco per un UILocalNotification
ripetere, è necessario:
- Capire la quantità di
repeatInterval
c'è stato tra la data di fuoco originale della notifica (vale a dire la sua proprietàfireDate
) e ora. - li Aggiungi a
fireDate
della notifica.
Ecco un approccio:
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];
Questo funziona in molti scenari, ma ecco uno scenario in cui non funzionerà:
Si supponga che:
- della comunicazione `fireDate è 01/01 alle 2:00 pm
-
repeatInterval
della notificaNSDayCalendaryUnit
(cioè ripetizione giornaliera) - La data di oggi è 08/01 alle 3:00 pm
Il codice qui sopra calcolare la differenza a 7 giorni (01/01 + 7 giorni = 08/01), aggiungerli al fireDate
, e quindi insieme nextFireDate
a 08/01 alle 14:00 . Ma questo è nel passato, vogliamo nextFireDate
essere 09/01 alle 14:00 !
Quindi, se si utilizza il codice di cui sopra e la vostra repeatInterval
è NSDayCalendaryUnit
, quindi aggiungere queste righe:
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];
}
Ho segnato questa risposta come wiki comunità, sentitevi liberi di modificarlo Se si è trovato un modo migliore per fare il calcolo!
Vorrei solo aggiungere il repeatInterval fino a quando le bugie data futura:
-(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;
}
Questo è in Swift 4 e l'utilizzo del calendario nextDate
Funz.
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)
}
}