2010-11-21 12 views
7

Sto cercando di recuperare i risultati della mia entità "MeterReading", che ha due proprietà, "timestamp" e "reading". "timestamp" è un NSDate. Sto cercando di recuperare un oggetto con una data esatta.Utilizzo di NSPredicate per scaricare NSDate esatto da NSManagedObjectContect

NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"MeterReading" inManagedObjectContext:context]; 
[request setEntity:entity]; 
NSLog(@"%f", [self.timestamp timeIntervalSince1970]); 

NSPredicate *pre = [NSPredicate predicateWithFormat:@"timestamp == %@", self.timestamp]; 
NSLog(@"%@", pre); 
[request setPredicate:pre]; 

Ora, self.timestamp è passato ad un altro ViewController anticipo, il NSLog mostra:

1290264372,210091

Il NSPredicate registra

timestamp == CAST (311957172.210091, "NSDate")

Prima domanda: perché i due numeri non sono uguali?

Seconda e più importante domanda: Nel ManagedContext, ho quattro voci con le date. Se uso "< =" invece di "==", ottengo risultati con una data inferiore a quella che ho passato, incluso quello che voglio avere. Perché non riesco a ottenere un'unica data con l'operatore "=="? Questo può essere correlato alla precisione delle mie date?

Grazie!

risposta

3

Questo è lo stesso problema dato che i controlli di uguaglianza in virgola mobile sono intrinsecamente insicuri. Man mano che i valori a virgola mobile vengono passati in rassegna, convertiti, usati in aritmetica, ecc., Perdono precisione a bit. Potrebbe essere necessario utilizzare un predicato più complesso che controlli invece le date entro una certa tolleranza; per esempio,

NSArray *timestamps = [NSArray arrayWithObjects: 
    [self.timestamp dateByAddingTimeInterval:-1], 
    [self.timestamp dateByAddingTimeInterval:1], 
    nil 
]; 

NSPredicate *pre = [NSPredicate predicateWithFormat:@"timestamp BETWEEN %@", timestamps]; 

che ti consente di ottenere qualsiasi oggetto corrispondente alla tua data più o meno un secondo.

+0

che ha quasi funzionato, grazie! passare l'array ha generato un errore, ma ho passato due nsdate manualmente al predicato e ora funziona. :) – denbec

+0

Oops, mi dispiace per quello! Sono contento che l'abbia aiutato, comunque. –

+0

Si noti che questo esempio non funzionerà con i dati principali. È necessario utilizzare qualcosa di simile: http://zdam.posterous.com/core-data-fetch-by-date – SpaceTrucker

3

Prima domanda: perché i due numeri non sono uguali?

Internamente, NSDate sembra per memorizzare un timestamp relativo al 1 ° gennaio 2001 e non il 1 ° gennaio 1970. Il numero 311957172.210091 probabilmente è il numero di secondi dal 01/01/2001.

Perché non è possibile ottenere un'unica data con l'operatore "=="? Questo può essere correlato alla precisione delle mie date?

Non so. Hai ispezionato il file SQLite direttamente per vedere quali timestamp sono memorizzati lì?

+0

Ricevo il timestamp dal mio negozio, lo passo a un altro controller di visualizzazione e cerco di eliminarlo. quindi sto cercando di recuperare lo stesso oggetto; Ho passato il timestamp in anticipo. questa è la cosa strana. c'è un altro modo per eliminare un oggetto gestito senza ottenere prima quell'oggetto? – denbec

+0

Perché si passa il timestamp in giro e non l'oggetto stesso? Non c'è bisogno di recuperarlo di nuovo. –

1

Per la vostra prima domanda, scommetto i numeri corrisponderanno se è stato utilizzato [self.timestamp timeIntervalSinceReferenceDate] invece che dal 1970.

Per la seconda domanda, la mia impressione è che la data nella memoria oggetto gestito non è esattamente lo stesso di self.timestamp. Ad esempio, potrebbe essere che la data memorizzata contenga solo un giorno e non un'ora? Potrebbe essere necessario eseguire alcuni arrotondamenti per ottenere quelli corrispondenti.

+0

In realtà, sto usando il timestamp o la data direttamente dall'oggetto gestito, lo passo ad un altro controller di visualizzazione, faccio altre cose e voglio cancellarlo di nuovo. quindi ho bisogno che l'oggetto lo elimini dal contesto e non conosco altro modo per cancellare un oggetto prima di recuperarlo di nuovo. quindi, dovrebbe essere la stessa data che sto usando. – denbec