2012-03-09 9 views
5

Mi aspetto (spero anche) che questa sia una domanda stupida, ma dopo aver lottato per molte ore con questo problema ho bisogno di qualche intuizione.Duplicazione dell'entità quando la modifica apportata da un child ManagedObjectContext viene trasferita (salvata) al suo genitore

La mia app iOS 5.1 utilizza MOC annidati, con un MOC figlio PrivateQueueConcurrency, chiamarlo MOC-Child, il cui padre è un MOC MainQueueConcurrency, chiamarlo MOC-Parent. MOC-Parent esegue il backup di una vista tabella che mostra le sue entità.

MOC-Child è utilizzato da un parser, che viene eseguito in modo asincrono su un thread non principale, per creare nuove entità che corrispondono a descrizioni di entità XML analizzate da una connessione URL e quindi inviare le nuove entità al MOC- Genitore, tramite un salvataggio sul MOC-Child, che li visualizza in una vista tabella. Questa grande opera:

1) Parser creates entity in MOC-Child 
2) Parser saves MOC-Child 
3) New entity is added to MOC-Parent 
4) New entity is displayed in MOC-Parent's table view 

Tuttavia, la descrizione di un dato soggetto in questo feed può cambiare nel tempo, in modo che l'entità che descrive deve essere modificato in app e la sua cella nella vista tabella aggiornata. Quindi, per ogni descrizione di entità nel feed, il parser tenta di recuperare l'entità (se presente) in MOC-Child che ha lo stesso id dell'entità descritta, e se ne esiste uno confronta i valori dell'entità esistente con i valori di descrizione in vedere se qualcosa è cambiato. Quando il parser rileva in questo modo che un'entità è stata modificata, aggiorna i valori dell'entità esistente in MOC-Child con i nuovi valori nella descrizione, quindi salva MOC-Child per inviare le modifiche a MOC-Parent.

Questo è dove le cose vanno male. Avevo pensato che le modifiche apportate a un'entità recuperata in MOC-Child, quando inviate al genitore salvandolo, semplicemente "appaiono" nella "stessa" entità in MOC-Parent. Tuttavia, quello che vedo accadendo è che l'entità modificata da MOC-Child è aggiunta a MOC-Parent, come se fosse un'entità completamente separata e nuova; con il risultato che MOC-genitore, e quindi la tabella di vista si spinge, finisce con due entità per ogni entità modificato:

1) Parser modifies existing entity in MOC-Child 
2) Parser saves MOC-Child 
3) Modified entity is _added to_ MOC-Parent 
4) Entity is displayed _twice_ in MOC-Parent's table view 

Che cosa dà? Cosa devo fare per modificare i valori di un'entità esistente in MOC-Parent, se non riesco a farlo all'interno di MOC-Child? E se dovessi essere in grado di farlo all'interno di MOC-Child, e se avessi altro da fare oltre al salvataggio del MOC-Child per ottenere le modifiche da apportare a MOC-Parent senza aggiungere l'entità una seconda volta?

Grazie in anticipo per qualsiasi aiuto o approfondimento che possiate offrire!

Carl

P.S. Un paio di chiarimenti. Quando dico che l'entità modificata viene aggiunta al MOC-Parent, intendo che NSFetchedResultsController che sta monitorando il MOC-Parent emette un tipo di modifica NSFetchedResultsChangeInsert (non un tipo di modifica NSFetchedResultsChangeUpdate) per l'entità modificata, anche se il " stessa "entità è già presente nel MOC-Parent.

Inoltre, quando dico "stessa" entità, intendo un'entità in MOC-Genitore che ha lo stesso ID fornito dalla descrizione (in questo caso un NSString) come l'entità che viene modificata nel MOC-child (non necessariamente lo stesso objectID, infatti apparentemente ha un oggetto differente).

+0

Ho lo stesso problema. Ho un NSFetchedResultsController collegato a contesti nidificati da un UIManagedDocument. Sto solo caricando da un server sul genitore in background e poi mostrando il bambino dal primo piano. Ma non funziona correttamente, non importa quale. Se chiudo l'app e la riapre, si carica perfettamente dalla memoria. Dispari. –

risposta

1

Immagino che, trattandosi di una domanda così vecchia, non è più un problema. Ma visto che recentemente mi sono trovato a lottare con una situazione simile, ho pensato di offrire la mia soluzione.

Scarico un array di migliaia di oggetti (associati a uno o più codici a barre) in un file XML, che quindi analizzo e salva in batch su un contesto di sfondo utilizzando una sottoclasse NSOperation. Il contesto del disco (connesso all'archivio persistente) ascolta NSManagedObjectContextDidSaveNotification, a quel punto salva anche (ricordarsi di farlo in un blocco).

[self.diskManagedObjectContext performBlockAndWait:^{ 
    NSError *error; 
    if (![self.diskManagedObjectContext save:&error]) { 
     NSLog(@"error saving to disk: %@",error); 
    } 
}]; 

La parte difficile è che nessuno dei codici a barre quelle degli oggetti potrebbero essere acquisite (nel contesto UI) prima che il file XML è stato completamente analizzato e le informazioni caricate nel database. E ho una vista tabella supportata da un NSFetchedResultsController che visualizza oggetti scansionati, che mostrano "sconosciuto" nei loro titoli fino a quando i dati non vengono recuperati dal carico in background. Come nella situazione di Carl, questi oggetti devono essere aggiornati quando il contesto di sfondo viene salvato.

Per gestire questo, io uso un sistema a tre contesto simile a quello in this question, con un contesto UI contesto e lo sfondo, che sono entrambi figli del mio contesto disco principale (che è legato alla memoria permanente). Quindi, durante l'analisi XML, eseguo una query sui codici a barre di un oggetto nel contesto di sfondo (che viene estratto anche dal contesto del disco padre) per vedere se un oggetto è già stato creato con quel codice a barre. Se lo è, aggiorno semplicemente le informazioni, risparmi, reimposta il contesto del disco e chiama refreshObject: mergeChanges: dal contesto dell'interfaccia utente per estrarre queste modifiche dal contesto del disco. Questo aggiorna correttamente la tabella senza creare duplicati.

Inizialmente ho provato questo utilizzando solo due contesti, un contesto di sfondo e un contesto di interfaccia utente, ma mentre non ho mai finito per creare oggetti duplicati, sono stato davvero bravo a appendere il thread dell'interfaccia utente.

Immagino che la domanda importante sia: come si modifica l'entità esistente? E non dimenticare il reset.

+0

In realtà, non ho ancora risolto questo problema, quindi è ancora abbastanza attuale, almeno per me. (Ho appena azzardato il problema eseguendo l'analisi come un'attività asincrona sul thread principale, lontano dall'ideale, ovviamente!) Quando avrò la possibilità, mi riprenderò il mio schema di analisi per provare la soluzione. Nel frattempo, grazie per le informazioni! –

+0

Sicuro. Se desideri maggiori informazioni quando lo provi, fammelo sapere e fornirò informazioni più dettagliate su una spiegazione. – enjayem

Problemi correlati