chiedere a mia domanda in modo efficace, si deve prima considerare lo scenario esatto che sto affrontando:Come posso garantire voci univoche in un archivio Dati principali in un contenitore di app condiviso utilizzato sia dall'app host sia da un'estensione?
General Setup
- Un host iOS 8 app.
- Uno o più estensioni iOS 8 (WatchKit, condivisione, ecc.) In bundle con l'app host.
- L'app host e tutte le estensioni condividono lo stesso archivio SQLite di dati di base nel contenitore del gruppo di app condiviso.
- Ogni app/estensione ha il proprio NSPersistentStoreCoordinator e NSManagedObjectContext.
- Ogni coordinatore di archivio permanente utilizza un archivio permanente che condivide le stesse risorse SQLite nel contenitore del gruppo di tutti gli altri archivi persistenti.
- L'app e tutte le estensioni utilizzano una base di codice comune per la sincronizzazione del contenuto da una risorsa API remota su Internet.
sequenza di eventi che portano al problema
l'utente avvia l'applicazione host. Inizia a recuperare i dati dalla risorsa API remota. Gli oggetti del modello di dati di base vengono creati in base alla risposta dell'API e "spostati" nel contesto dell'oggetto gestito dell'app host. Ogni entità API ha un ID univoco che lo identifica nel back-end API remoto. Con "upsert", intendo che per ogni entità API, l'app host crea solo una nuova voce in Dati principali se non è possibile trovare una voce esistente per un determinato ID univoco.
Nel frattempo, l'utente avvia anche una delle estensioni dell'app host. Anch'esso esegue una sorta di recupero dalla stessa API remota. Prova anche a eseguire un "upsert" durante l'analisi delle risposte API.
Il problema: Cosa succede se sia l'app host che un'estensione tentano di eseguire l'upsert di una voce di dati di base per la stessa entità API allo stesso tempo? Per vedere come questo potrebbe accadere, diamo un'occhiata alla sequenza di eventi per un upsert:
Core Data upsert Sequenza:
- Il codice API di analisi analizza l'uniqueID per un dato API entità.
- Il parser esegue un recupero dei dati di base per qualsiasi voce corrispondente a un predicato in cui
uniqueID
è uguale al uniqueID analizzato. - Se non viene trovata una voce esistente, il parser inserisce una nuova voce Dati principali per questa entità API, imposta l'attributo
uniqueID
all'ID univoco analizzato. - Il parser salva il contesto dell'oggetto gestito, che trasferisce i nuovi dati di immissione nell'archivio di supporto SQLite.
problema in dettaglio
Supponiamo l'applicazione host e l'estensione sono parsing indipendentemente una risposta API per la stessa entità API allo stesso tempo. Se l'app host e un'estensione raggiungono il passaggio 3 prima che uno di essi abbia completato il passaggio 4, entrambi tenteranno di inserire una nuova voce di dati principali per lo stesso ID univoco. Quando raggiungono il passaggio 4 e chiamano save:
nei rispettivi contesti degli oggetti gestiti, i dati di base creeranno felicemente voci duplicate.
Per quanto ne so, Core Data non ha modo di contrassegnare un attributo come univoco. Ho bisogno di un Core Data equivalente a SQLite INSERT OR IGNORE
+ UPDATE
combo.. Oppure ho bisogno di un modo per "bloccare" il backing store SQLite del negozio persistente, che sembra una ricetta per i problemi.
Esiste un approccio noto a questo problema piuttosto nuovo introdotto dalle estensioni di iOS 8?
Perché non annullare/sospendere GET richieste quando l'host passa in modalità sfondo? – 3lvis
Sto ottenendo queste voci duplicate quando Core Data diventa troppo stupido, per quello nel passaggio 2 di Core Data Upsert Sequence: se c'è più di un risultato, elimino gli inserimenti aggiuntivi. https://github.com/NSElvis/NSManagedObject-ANDYMapChanges/blob/master/Source/NSManagedObject%2BANDYMapChanges.m#L52 – 3lvis