2012-02-01 11 views
15

Ho un problema con un'applicazione shoebox iCloud e spero che qualcuno possa aiutarmi (ho passato molte ore a combatterlo invano).iCloud + CoreData: come evitare la duplicazione dei dati precompilati?

L'app: - Una semplice applicazione in stile libreria - contenente un insieme di categorie (Cat1 .. CatN) contenenti ciascuna elementi (elemento1 ... elementoM). Ho usato iPhoneCoreDataRecipes di Apple per configurare lo stack iCloud CoreData.

Tutto funziona quasi perfettamente con iCloud tranne - ci dovrebbe essere un certo numero di categorie vuote pre-riempite che l'utente può iniziare a utilizzare una volta che ha aperto l'app per la prima volta (può anche essere offline in quel momento). Ed ecco il diavolo.

Ecco quello che faccio - Una volta che la mia persistentStoreCoordinator è configurato mando notifica

dispatch_async(dispatch_get_main_queue(), ^{ 
    [[NSNotificationCenter defaultCenter] 
     postNotificationName: @"RefetchAllDatabaseData" 
         object: self 
        userInfo: nil]; 
    }); 

che viene ricevuto dal mio MasterViewController. Quando viene ricevuta la notifica, MasterViewController controlla il numero di categorie nella memoria. Se il numero di categorie disponibili è uguale a 0, vengono inserite le categorie pre-riempite.

CRONACA - Io uso NSMergeByPropertyObjectTrumpMergePolicy per il mio ManagedObjectContext

Il problema: Questo metodo funziona bene per il 1 ° dispositivo. Ma per il secondo dispositivo le categorie predefinite da iCloud sono spesso ricevute successivamente rispetto a persistenteStoreCoordinator è stato impostato (e le categorie predefinite inserite dal secondo dispositivo). Alla fine ho 2 set di categorie con lo stesso nome su entrambi i dispositivi.

Qualche idea su come questo può essere risolto?

Soluzioni provate: Ho provato 2 strategie per risolvere questo problema. Entrambi iniziano allo stesso modo. Dopo che io chiamo

[moc mergeChangesFromContextDidSaveNotification: note]; 

chiamo

[self materializeKeysWithUserInfo: note.userInfo forContext: moc]; 

molte grazie a Jose Ines Cantu Arrambide da https://devforums.apple.com/thread/126670?start=400&tstart=0 per il suo codice di riferimento - In sostanza

materializeKeysWithUserInfo:forContext: 

ottenere managedObjectIds da note.userInfo e recupera oggetti corrispondenti da ManagedObjectContext inserendoli in un dizionario.

Strategia 1:

  • Tutte le mie categorie hanno la creazione di timestamp.
  • sull'inserto da iCloud, ottenere coppie di categorie con lo stesso nome se presente
  • Selezionare vecchie categorie duplicati
  • spostare i loro oggetti a più recenti categorie duplicati
  • eliminare le categorie duplicati anziani

Questi strategia efficace rimuove i duplicati su entrambi i dispositivi anche prima che compaiano nell'interfaccia utente MA

1) gli elementi dal primo de i vice si perdono sul secondo dispositivo - quando arrivano al secondo dispositivo la loro categoria padre è assente e il loro campo categoria è uguale a zero quindi non so dove metterli.

2) in un breve lasso di tempo gli oggetti persi sul secondo dispositivo si perdono anche per il primo a causa di conflitti.

3) alcuni oggetti provenienti dal secondo dispositivo vengono persi a causa di conflitti.

ho cercato di preferire le categorie più anziani contro il più recente, ma non ha dato alcun effetto

Strategia 2:

  • Tutte le mie categorie hanno la creazione di timestamp.
  • Tutte le categorie sono obsoleti campo booleano impostato NO sulla creazione
  • sull'inserto da iCloud, ottenere coppie di categorie con lo stesso nome se presente
  • Selezionare vecchie categorie duplicati
  • spostare i loro oggetti di recente categorie duplicati
  • marchio vecchie categorie con obsoleti = SI

Questi strategia quasi sempre rimuove i duplicati su entrambi i dispositivi prima ancora che appaiono nell'interfaccia utente MA

la maggior parte (o tutti) gli elementi da entrambi i dispositivi sono sempre persi a causa di una serie di conflitti su categorie e articoli.

Alcune riflessioni conclusive:

Sembra che questi strategia non funziona, come si comincia contemporaneamente cambiando ob contenuti entrambi i dispositivi, mentre iCloud non è adatto per tale modello.

Nei miei test ho avuto entrambi i dispositivi in ​​esecuzione contemporaneamente. Non posso trascurare un caso in cui un utente felice che ha appena acquistato il suo secondo iDevice installa la mia app sul secondo dispositivo (con il primo dispositivo che esegue l'app) e si perde tutti i suoi articoli in pochi minuti.

Qualche idea su come risolvere questa situazione? Pensi che iCloud + CoreData sia pronto per la produzione?

Strategia 3

Ho cercato di mettere un database pre-riempita (copiandolo da pacco) per il percorso appropriato. Ha funzionato in parte - non ho più categorie preriempita duplicazione MA gli elementi aggiunti alle categorie pre-riempite non la sincronizzazione tra i dispositivi.

iCloud non è a conoscenza dei dati presenti nel database prima della configurazione di iCloud - il mio secondo dispositivo riceve gli elementi, inseriti nel primo dispositivo in categorie precompilate, con categoria = nullo.

I prodotti in aggiunta categorie (così come le categorie stessi) inseriti nella archiviazione dopo la configurazione di iCloud si sincronizzano correttamente.

risposta

3

Strategia 1 con alcune modifiche che sembrava essere una soluzioni di lavoro (con alcuni difetti però).

Legenda:

  • primo dispositivo - ha iniziato online senza alcun contenuto nel 2 ° dispositivo iCloud
  • - ha iniziato più tardi del primo e offline.Poi si fa on-line, dopo alcuni articoli aggiunti

Quindi, ecco la strategia di aggiornamento:

  • Tutte le mie categorie hanno creazione timestamp

  • Le categorie non possono essere rinominato (solo aggiunto o cancellato - questo è fondamentale)

  • Tutti i miei articoli ha ve un campo categoryName stringa che ottiene il suo valore alla creazione dell'oggetto e viene aggiornato ogni volta che l'elemento viene spostato in una categoria diversa: questa informazione ridondante ridondante aiuta a raggiungere il successo;

Su inserimento di nuovi Categorie:

  • sull'inserto da iCloud, ottengo coppie di categorie con lo stesso nome, se eventuali

  • Select più recenti categorie duplicati (che probabilmente avranno meno oggetti di quelli vecchi, quindi avremo meno dance in iCloud)

  • spostare i loro articoli se un altro per anziani categorie duplicati

  • Eliminare più recenti categorie duplicati

Su inserimento di nuovi Articoli - se la voce appartiene a cancellato categoria:

  • CoreData tenta di unirlo e fallisce in quanto non esiste più alcuna categoria padre (molti errori nella console). Promette di inserirlo più tardi.

  • Dopo qualche breve tempo fa unire e inserire l'oggetto in deposito, ma con NIL categoria

  • Qui prendiamo il nostro articolo su, scoprire la sua categoria genitore da categoryName e lo mise al corretta categoria

VOILA! - non duplica & tutti felici

Un paio di note:

  1. ricevo una danza di elementi appartenenti alla 2 ° dispositivo (quelli che verranno con la categoria nullo al primo dispositivo) su entrambi i dispositivi.Dopo un paio di minuti tutto è stabilizzato
  2. Nessun elemento è perduto anche se
  3. La danza avviene solo sulla prima sincronizzazione iCloud del 2 ° (o qualsiasi altro dispositivo successiva)
  4. Se il secondo dispositivo viene avviato linea per la prima volta la possibilità che il caso delle categorie duplicate appaia è solo del 25% - testata sulla connessione 3G - quindi la danza non dovrebbe riguardare la maggior parte degli utenti
+0

Konstiantyn, ho seguito le tue conversazioni sullo sviluppatore. luogo. Apprezzo molto che tu abbia aggiunto la domanda qui - Vorrei che ci fossero più commenti! Questa strategia ha funzionato per te? Hai considerato di avere un localStore precostruito, come nell'esempio SharedCoreData? Cordiali saluti –

+0

È possibile ridenominare le proprie categorie, purché sia ​​possibile distinguere tra record creati dal sistema e record creati dall'utente. Ho usato un paio di attributi 'createDate' e' updateDate' per [determinare se un elemento di dati deve essere deduplicato] (http://cutecoder.org/programming/seeding-icloud-core-data/). – adib

+0

Ciao ragazzi, ho dovuto fermarmi a un certo punto 2 anni fa e non ho rivisitato CoreData + iCloud da allora. @adib: grazie per il tuo commento Userò questa tecnica più tardi se necessario. –

Problemi correlati