2013-04-12 24 views
6

Ho già trascorso alcune ore su quello e non riesco a trovare una soluzione. In primo luogo, alcune specifiche di quello che devo:Incoerenza dei dati principali - il recupero talvolta non restituisce nulla

  • Objective-C iOS 6 app con Core Data
  • Core Data è inizializzato da UIManagedDocument, che ha auto-saving acceso
  • ManagedContext da UIManagedDocument è memorizzato in una variabile statica e riutilizzata in tutta l'app
  • L'app utilizza RestKit e io utilizzo la categoria ActiveRecord che fornisce.

Ho un modello con entità Team. Nell'app è presente un controller di visualizzazione Elenco squadra, che carica i team dal back-end. Il backend restituisce l'array JSON, che contiene tra gli altri l'ID della squadra. Memorizzo questo ID nel campo "id" del mio modello e, mentre eseguo l'iterazione sulla risposta del server, cerco se il team per un dato ID esiste già. Se lo fa, aggiorno solo le sue informazioni e passo l'oggetto, se no - lo creo per primo.

E questo è dove diventa bizzarro. Questo funziona per il 90% del tempo. Posso caricare il controller Elenco squadra, andare oltre nell'app, tornare al controller (che carica di nuovo i dati) e tutto va bene la maggior parte del tempo. Di tanto in tanto, tuttavia, la mia richiesta di recupero non restituirà nulla. Come in:

NSArray *results = [context executeFetchRequest:request error:&error]; 

restituirà l'array vuoto e l'errore è anche vuoto. Nulla sul server è in continua evoluzione. La richiesta, quando si tenta di eseguire il debug di esso, appare come segue:

<NSFetchRequest: 0x127a0e20> (entity: Team; predicate: (id == "123"); sortDescriptors: ((null)); limit: 1; type: NSManagedObjectResultType;) 

Quando l'anteprima del negozio sqlite in un app esterna, vedo che la voce della squadra per questo ID è presente, e in altri 90% volte viene effettivamente caricato. Che cosa è ancora più bizzarro, quando ho girato su SQLDebug posso vedere:

2013-04-12 12:00:27.934 SportLink[10831:c07] CoreData: annotation: fetch using 
NSSQLiteStatement <0x12656d10> on entity 'Team' with sql text 'SELECT 0, t0.Z_PK, 
t0.Z_OPT, t0.ZACI1, t0.ZACI2, t0.ZACI3, t0.ZALTFIRSTNAME, t0.ZALTSECONDNAME, t0.ZCOLOR1, 
t0.ZCOLOR2, t0.ZGENDER, t0.ZICON, t0.ZID, t0.ZLOCATION, t0.ZLOGO1, t0.ZLOGO2, t0.ZNAME, 
t0.ZTYPE, t0.ZSPORT FROM ZTEAM t0 WHERE t0.ZID = ? LIMIT 133' returned 6 rows 

il che significa che l'archivio di backup in realtà andò a prendere i dati, ma per qualche ragione non ha superato lungo. Ora:

  • Sto facendo tutto nel thread principale, quindi questo non è un problema
  • Credo che il salvataggio automatico non è anche un problema, perché questo può accadere anche quando chiudo l'applicazione e apro di nuovo con i dati già presenti.

Qualche idea su cosa diavolo sta succedendo qui?

Modifica: ho profilato l'app con Strumenti. Ho appena inserito il VC problematico, quindi ho inserito il controller figlio e lasciato, ripetuto un paio di volte fino a quando il problema ha iniziato a manifestarsi. Ecco i risultati. Forse sarà più facile sapere cosa sta succedendo a partire da qui:

Instruments output

+0

Quando si attiva la richiesta in 'TeamListVC'? Cosa stai facendo quando i risultati sono stati caricati? È inoltre possibile registrare '[risultati conteggio]' dopo la richiesta di tracciare un po 'di più. – flashfabrixx

+0

prova a impostare lo stalenessInterval del contesto principale su 0 –

+0

@DanShelly sfortunatamente questo non ha aiutato. – mav

risposta

5

Dopo alcuni giorni di indagine, ho finalmente trovato la causa di questo bug. Il codice che è stato il recupero entità della squadra si presentava così:

Team *team = [Team findFirstByAttribute:WSK_ID withValue:data[WSK_ID] inContext:moc]; 

WSK_ID è solo una definizione per @"id".data è un dizionario che ho ricevuto da RestKit, da una risposta JSON. Poiché non è stato assegnato a nessun tipo, probabilmente era una NSString, mentre la proprietà id dell'entità Team si aspettava NSNumber. Mentre io non so cosa ha fallito solo a volte, cambiando questo bit a:

Team *team = [Team findFirstByAttribute:WSK_ID withValue:@([data[WSK_ID] intValue]) inContext:moc]; 

I.e. il casting della stringa ID su int, e poi il boxing con NSNumber ha risolto il problema.

+0

Sqlite3 su iOS è assolutamente terribile quando si tratta di interoperabilità, conversione di tipi, ecc., Anche se non si utilizza CoreData. Nella mia esperienza, ho scoperto che mentre CoreData è utile in scenari semplici, aggiunge anche complessità nascondendo determinati dati. – Brandon

Problemi correlati