2010-09-09 13 views
6

Penso di aver compreso il messaggio di errore: CoreData non è riuscito a soddisfare un errore, ma non sono sicuro di come dovrei gestirlo.CoreData non è riuscito a soddisfare un errore quando gli oggetti vengono aggiornati dal servizio HTTP

Abbiamo un'applicazione in cui utilizziamo Core Data per mantenere i dati restituiti da un servizio JSON. Oggi sto facendo il seguente.

  1. Fetch oggetto locale da archivio permanente e tornare alla UI
  2. Chiedi server se l'oggetto viene aggiornato - quando ho la risposta, aggiornare i dati Nucleo gestito oggetto
  3. Aggiornamento UI con l'oggetto aggiornato

Il problema è; anche se non utilizzo thread multipli, a volte viene visualizzato un errore quando la richiesta HTTP elimina gli oggetti gestiti che la mia UI ha conservato. Ho provato a recuperare gli oggetti con returnObjectsAsFaults su NO. Ho pensato quindi di poter accedere a tutte le relazioni e le proprietà di un oggetto gestito anche se è stato cancellato (purché l'interfaccia utente l'abbia conservato).

Come si può risolvere questo problema?

Ho pensato di poter utilizzare NSManagedObjectContext separato per leggere e scrivere. Ho fatto questo test:

MyAuthorMO *authorUpdate = [[MyAuthorMO alloc] init]; // I have made this init insert the object into the updateContext 
authorUpdate.firstname = @"Hans"; 
authorUpdate.lastname = @"Wittenberg"; 
authorUpdate.email = @"[email protected]"; 

NSManagedObjectContext *updateContext = [[MyCoreManager getInstance] managedObjectContext]; 

NSError *error = nil; 
[updateContext save:&error]; 

NSManagedObjectContext *readContext = [[MyCoreManager getInstance] readOnlyContext]; 

NSFetchRequest *fetchRequest = [managedObjectModel fetchRequestFromTemplateWithName:@"authorByEmail" substitutionVariables:[NSDictionary dictionaryWithObject:@"[email protected]" forKey:@"EMAIL"]]; 
[fetchRequest setReturnsObjectsAsFaults:NO]; 

NSArray *authors = [readContext executeFetchRequest:fetchRequest error:&error]; 

MyAuthorMO * readAuthor = [authors objectAtIndex:0]; 

// Delete the author with update context: 
[updateContext deleteObject:authorUpdate]; 
[updateContext save:&error]; 

NSLog(@"Author: %@ %@, (%@)", readAuthor.firstname, readAuthor.lastname, readAuthor.email); 

Il registro viene emesso bene finché io uso il readContext per il recupero. Se utilizzo l'updateContext per il recupero, ottengo un'eccezione. Questo sembra promettente, ma temo di incappare in problemi in una fase successiva. Presto o tardi tenterò probabilmente di accedere a una proprietà che non è stata recuperata completamente (un errore). Come posso ottenere il comportamento che sto cercando?

+0

Nick, probabilmente hai ragione. Ho letto i miei post precedenti e ho accettato le migliori soluzioni. Grazie per il tuo commento. – Andi

risposta

14

Non si devono conservare oggetti gestiti che il contesto ha rilasciato. Lascia che sia il contesto a farlo per te.

Il problema è che gli oggetti gestiti possono esistere come errori o oggetti attualizzati. Quando ne mantieni uno, puoi conservare l'errore che non contiene dati. Anche se si mantiene l'oggetto reale, l'oggetto potrebbe non funzionare correttamente una volta che è stato separato dal suo contesto.

Per gestire lo scenario, è necessario un contesto per l'interfaccia utente e quindi un contesto per il server. Dopo che entrambi i contesti apportano modifiche, è necessario unire il contesto per garantire che entrambi siano correttamente aggiornati rispetto all'archivio.

L'interfaccia utente deve essere configurata in modo da riflettere lo stato del modello dati, non è necessario che parti del modello dati dipendano dallo stato dell'interfaccia utente.

+1

Sono d'accordo con te, ma ho alcune domande di follow-up. Non sto mantenendo il MO, ma se lo uso da qualche parte, probabilmente potrebbe essere mantenuto senza che io lo sappia. Va bene aggiungere un MO a NSArray o NSDictionary? Se è così, allora verrà mantenuto ... Devo unire il contesto, o potrei semplicemente aspettare la prossima volta che prendo da "read" -context "? Temo che i miei dati vengano corrotti se io unire due contesto in cui l'oggetto che sto attualmente sta visualizzando viene cancellato (con "scrittura" -contesto). – Andi

+1

Non ero chiaro.Intendevo che non dovresti cercare di conservare un oggetto gestito che un contesto ha eliminato. Quello diventerà disordinato. Dovresti unire il contesto, ma dovrai congelare l'interfaccia mentre il modello si aggiorna. Guarda come NSFetchedResultsController gestisce questo problema esatto con l'aggiornamento dei dati mentre i dati vengono visualizzati in una tabella. Il blocco dell'interfaccia utente è di solito completamente ignorato dall'utente. Se si dispone di dati che potrebbero essere eliminati mentre l'utente sta lavorando con esso, è necessario ripensare la progettazione. L'utente dovrebbe controllare tali cancellazioni. – TechZen

0

Ho avuto lo stesso problema nel mio database perché mi riferisco a un oggetto che non esiste (perché lo rimuovo con altri oggetti relazionati). La mia soluzione era impostare "Nessuna azione" nella mia relazione.

Problemi correlati