2009-11-19 1 views
6

In un progetto precedente, ho creato un'app per iPhone per 2.2.x che utilizzava SQLite. Aveva dati esistenti (in formato XML) che dovevano essere pre-caricati nella build. Così ho scritto un piccolo strumento che ha usato libxml2 per analizzare l'XML, e quindi scrivere un database SQLite, che poi è stato incluso direttamente nella build come risorsa. Questo ha funzionato alla grande.Pre-carica i dati esistenti in un'app per iPhone basata su Core Data?

In poche settimane avvierò un nuovo progetto per un altro client con gli stessi parametri. Avrò alcuni dati esistenti che avrò bisogno di analizzare e riversare in un file che l'app mostrerà. Tuttavia, questa volta vorrei utilizzare Core Data e creare l'app per i dispositivi 3.x. Tuttavia, non ho accesso diretto e esplicito allo schema del database sottostante utilizzato da Core Data. (Che è il punto di Core Data)

Come posso pre-caricare i dati esistenti in un'app per iPhone basata su Core Data? Posso automatizzare il processo (simile a quello che ho fatto sopra con SQLite)?

risposta

3

Supponendo che si stia utilizzando CoreData con un supporto SQLite, quindi assolutamente. L'opzione più diretta sarebbe lasciare che l'applicazione generi lo schema per te, quindi usando quel DB vuoto/shell, esegui lo strumento di migrazione da xml a sql. Dovresti semplicemente aggiornare il tuo strumento per tenere conto della struttura che CoreData genera per te da xcdm.

In alternativa, è possibile utilizzare lo strumento per scrivere un db sqlite incluso nel pacchetto, quindi in fase di avvio all'avvio, leggere i dati dal db sqlite, sputarlo in CoreData e proseguire. Questo userebbe il DB sqlite come contenitore per i "dati di precaricamento" e tutte le ulteriori interazioni di dati all'interno dell'archivio dati di CoreData.

Probabilmente è una questione di preferenza.

+1

Per applicazione, vuoi dire che Xcode genera lo schema? Oppure lo schema viene creato solo in fase di esecuzione? –

+0

Non sono sicuro al 100%. Voglio dire che è generato in fase di esecuzione (credo che parte di CoreData init sia quello di aggiornare un data store se necessario), ma è necessario verificarlo. –

+0

Xcode non genererà lo schema. È un'operazione di runtime. –

2

Non credo che Core Data fornisca intrinsecamente questo tipo di funzionalità. Se fossi nei tuoi panni, scriverei un piccolo strumento che eseguiva l'analisi XML e faceva tutto il necessario per creare il modello Core Data da quei dati e mantenerlo. Quindi, sposta semplicemente il database sqlite che Core Data genera nel tuo progetto reale.

Quindi forse scrivere un codice che copia quel database predefinito nella posizione corretta su iPhone se un database non esiste già lì. Ciò consentirà anche di ripristinare facilmente i dati "puliti" se ti trovi in ​​uno stato negativo poiché puoi semplicemente eliminare il file del database ed eseguire nuovamente l'app.

+0

Ho effettivamente fatto qualcosa proprio come quello che hai descritto, ma invece di farlo in due passaggi lo faccio in uno. Creo il negozio .sql dove è necessario nell'iPhone. Tuttavia, questo approccio non causerebbe problemi quando è il momento di inviare l'app all'app store? Come risolveresti questo problema? – Stunner

+0

Perché ciò potrebbe causare problemi? Non penso che includere i dati seme con la tua app sia contrario alle linee guida dell'App Store. –

2

È possibile seguire un approccio simile. È probabile che il modo più semplice sia configurare il contesto gestito dei dati principali e quindi leggere il file XML, creando gli oggetti gestiti mentre si analizza il file XML.

NSManagedObjet *managedObject = [[NSEntityDescription insertNewObjectForEntityForName:@"DataTypeName" 
                    inManagedObjectContext:managedContext] retain]; 

    [managedObject setValue:@"some data" forKey:@"keyName"]; 
    /* ... */ 
+0

Questa è una soluzione valida. Tuttavia, preferirei fare questo tipo di analisi "offline", quindi l'app vede sempre solo un file DB SQLite. –

10

Sono un po 'in ritardo per questa festa, ma sto facendo qualcosa di simile per GroceryList. Ho dati memorizzati in file plist di cui ho bisogno nel mio negozio sqlite CoreData. Ho scritto uno strumento di base della linea di comando che gira sul mio Mac, che analizza i file plist e quindi utilizzando il mio modello di oggetti Core Data crea un archivio SQLite. Eseguo questo strumento da riga di comando come parte della mia build (per alcune configurazioni di build) in modo da poter rigenerare i dati a piacimento. Per creare questo tipo di strumento in xcode, seleziona File -> Nuovo progetto -> Mac OS X -> Strumento riga di comando e seleziona "Dati principali" dal menu "tipo". Ecco alcuni esempi di codice:

#import <objc/objc-auto.h> 

int main (int argc, const char * argv[]) { 

    objc_startCollectorThread(); 

    //You may not know this, but NSUserDefaults can be used to parse command line arguments! 
    //in this case, the arguments are passed in like this: 
    // -fullMomPath /hd/some/path/file.mom -fullStorePath /hd/some/path/file.sql 
    //by passing in the storePath, the calling script knows where the sqlite file will be and can copy it to the resulting application bundle 
    NSUserDefaults *args = [NSUserDefaults standardUserDefaults]; 
    NSString *momPath = [args stringForKey:@"fullMomPath"]; 
    NSString *storePath = [args stringForKey:@"fullStorePath"]; 

    // Create the managed object context 
    NSManagedObjectContext *context = managedObjectContext(momPath, storePath); 


    //build and save your NSManagedObjects here 
    //in my case, i parse some plist files and create GroceryList type stuff, but whatever you do is your business. 

    return 0; 
} 

NSManagedObjectModel *managedObjectModel(NSString* momPath) { 

    static NSManagedObjectModel *model = nil; 

    if (model != nil) { 
     return model; 
    } 

    NSURL *modelURL = [NSURL fileURLWithPath:momPath]; 
    model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 

    return model; 
} 



NSManagedObjectContext *managedObjectContext(NSString* momPath, NSString* storePath) { 

    static NSManagedObjectContext *context = nil; 
    if (context != nil) { 
     return context; 
    } 

    context = [[NSManagedObjectContext alloc] init]; 

    NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: managedObjectModel(momPath)]; 
    [context setPersistentStoreCoordinator: coordinator]; 

    NSString *STORE_TYPE = NSSQLiteStoreType; 

    NSURL *url = [NSURL fileURLWithPath:storePath]; 

    NSError *error; 
    NSPersistentStore *newStore = [coordinator addPersistentStoreWithType:STORE_TYPE configuration:nil URL:url options:nil error:&error]; 

    if (newStore == nil) { 
     NSLog(@"Store Configuration Failure\n%@", 
       ([error localizedDescription] != nil) ? 
       [error localizedDescription] : @"Unknown Error"); 
    } 

    return context; 
} 
+0

Grazie per la condivisione! Tuttavia sto avendo qualche problema nel determinare il percorso MOM. Vedi http://stackoverflow.com/questions/4600312/how-to-get-path-of-momd-file-in-core-data Grazie! – Stunner