Nella nostra app in fase di sviluppo utilizziamo i dati di base con un backing store SQL per archiviare i nostri dati. Il modello a oggetti per la nostra app è complesso. Inoltre, la quantità totale di dati offerti dalla nostra app è troppo grande per rientrare in un pacchetto di app iOS (iPhone/iPad/iPod Touch). Poiché i nostri utenti sono, in genere, interessati solo a un sottoinsieme dei dati, abbiamo suddiviso i nostri dati in modo tale che l'app sia fornita con un sottoinsieme (anche se ~ 100 MB) degli oggetti dati nel pacchetto di app. I nostri utenti hanno la possibilità di scaricare oggetti dati aggiuntivi (di dimensioni ~ 5 MB a 100 MB) dal nostro server dopo che pagano per i contenuti aggiuntivi tramite acquisti in-app di iTunes. I file di dati incrementali (esistenti nei backing backup di tipo sqlite) utilizzano la stessa versione xcdatamodel dei dati forniti con il pacchetto; non vi sono modifiche al modello dell'oggetto. I file di dati incrementali vengono scaricati dal nostro server come file sqlite con gzip. Non vogliamo gonfiare il nostro pacchetto di app spedendo i contenuti incrementali con l'app. Inoltre, non vogliamo fare affidamento su query su webservice (a causa del complesso modello di dati). Abbiamo testato il download dei dati sqlite incrementali dal nostro server. Siamo stati in grado di aggiungere l'archivio dati scaricato al persistentStoreCoordinator condiviso dell'app. Che cos'è un modo efficace per unire due archivi persistenti di dati core iOS?
{
NSError *error = nil;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:defaultStoreURL options:options error:&error])
{
NSLog(@"Failed with error: %@", [error localizedDescription]);
abort();
}
// Check for the existence of incrementalStore
// Add incrementalStore
if (incrementalStoreExists) {
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:incrementalStoreURL options:options error:&error])
{
NSLog(@"Add of incrementalStore failed with error: %@", [error localizedDescription]);
abort();
}
}
}
Tuttavia, ci sono due problemi con facendo in questo modo.
- dati recuperare i risultati (ad esempio, con NSFetchResultController) presentarsi con i dati dal incrementalStoreURL aggiunto alla fine dei dati dal defaultStoreURL.
- Alcuni degli oggetti sono duplicati. Ci sono molte entità con i dati di sola lettura nel nostro modello di dati; questi vengono duplicati quando aggiungiamo il secondo persistentStore a persistentStoreCoordinator.
Idealmente, vorremmo Core Data di unire i grafi di oggetti da due negozi persistenti in uno (non ci sono relazioni condivise tra i dati dei due negozi al momento del download di dati). Inoltre, vorremmo rimuovere gli oggetti duplicati. Cercando sul web, abbiamo visto un paio di domande da parte di persone che tentavano di fare la stessa cosa che stiamo facendo, come ad esempio this answer e this answer. Abbiamo letto Marcus Zarra's blog on importing large data sets in Core Data. Tuttavia, nessuna delle soluzioni che abbiamo visto ha funzionato per noi. Non vogliamo leggere e salvare manualmente i dati dall'archivio incrementale all'archivio predefinito poiché pensiamo che questo sarà molto lento e soggetto a errori sul telefono. C'è un modo più efficiente di fare l'unione?
Abbiamo tentato di risolvere il problema implementando una migrazione manuale come segue. Tuttavia, non siamo stati in grado di ottenere con successo l'unione. Non siamo molto chiari sulla soluzione suggerita dalle risposte 1 e 2 di cui sopra. Il blog di Marcus Zarra ha affrontato alcuni dei problemi che avevamo all'inizio del nostro progetto importando il nostro grande set di dati in iOS.
{
NSError *error = nil;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSMigrationManager *migrator = [[NSMigrationManager alloc] initWithSourceModel:__managedObjectModel destinationModel:__managedObjectModel];
if (![migrator migrateStoreFromURL:stateStoreURL
type:NSSQLiteStoreType
options:options
withMappingModel:nil
toDestinationURL:destinationStoreURL
destinationType:NSSQLiteStoreType
destinationOptions:nil
error:&error])
{
NSLog(@"%@", [error userInfo]);
abort();
}
}
Sembra che l'autore di risposta 1 ha finito per leggere i suoi dati dall'archivio incrementale e il salvataggio al negozio di default. Forse abbiamo frainteso la soluzione suggerita da entrambi gli articoli 1 & 2. La dimensione dei nostri dati potrebbe impedirci di leggere e reinserire manualmente i nostri dati incrementali nell'archivio predefinito. La mia domanda è: qual è il modo più efficiente per ottenere i grafici degli oggetti da due persistentStores (che hanno lo stesso objectModel) per unire in un unico persistentStore?
La migrazione automatica funziona piuttosto bene quando si aggiungono nuovi attributi di entità ai grafici degli oggetti o si modificano le relazioni. Esiste una soluzione semplice per unire dati simili nello stesso archivio persistente che sarà abbastanza flessibile da fermarsi e riprendere - con la migrazione automatica?
Dove è Marcus Zarra quando ho bisogno di lui? Ho fatto qualche progresso usando il metodo [NSPersistentStore migratePersistentStore: toURL: options: withType: error]. Ho solo bisogno di un po 'di codice di pulizia per arrivare dove devo essere. – Sunny
Sto litigando con la stessa cosa. Puoi pubblicare ciò che hai inventato finora? Mi sono perso. – damon
Fatto! Fammi sapere come va a finire per te. – Sunny