2009-11-19 12 views
6

In einem früheren Projekt habe ich eine iPhone-App für 2.2.x erstellt, die SQLite verwendet. Es hatte vorhandene Daten (in XML-Form), die in den Build vorinstalliert werden mussten. Also schrieb ich ein kleines Tool, das libxml2 benutzte, um das XML zu parsen und dann eine SQLite-Datenbank zu schreiben, die dann direkt in den Build als Ressource eingefügt wurde. Das hat super geklappt.Vorhandene Daten in eine Core Data-basierte iPhone App laden?

Ich werde ein neues Projekt für einen anderen Client in wenigen Wochen beginnen, die meist die gleichen Parameter. Ich werde einige vorhandene Daten haben, die ich analysieren und in eine Datei ablegen muss, die die App anzeigt. Dieses Mal möchte ich jedoch Core Data verwenden und die App für 3.x-Geräte erstellen. Ich habe jedoch keinen expliziten und direkten Zugriff auf das zugrunde liegende Datenbankschema, das von Core Data verwendet wird. (Welche Art von dem Punkt der Core Data ist)

Wie kann ich Vorbelastung vorhandenen Daten in ein Core Data-basierten iPhone app? Kann ich den Prozess automatisieren (ähnlich wie bei SQLite)?

Antwort

3

Angenommen, Sie sind mit Coredata mit einer SQLite-Unterstützung, dann auf jeden Fall. Die direkteste Option wäre, die Anwendung das Schema für Sie erstellen zu lassen, und dann mit dieser leeren/Shell-DB das xml-to-sql-Migrationstool auszuführen. Sie müssten lediglich Ihr Tool aktualisieren, um die Struktur zu berücksichtigen, die CoreData für Sie von der xcdm generiert.

Alternativ können Sie Ihr Werkzeug verwenden, um eine sqlite db zu schreiben, die in Ihrem Bundle enthalten ist, und dann zur Laufzeit beim Start die Daten aus der sqlite db einlesen, in CoreData spucken und weitermachen. Dies würde Ihre sqlite DB als Container für die "Preload-Daten" und alle weiteren Dateninteraktionen in CoreDatas Datenspeicher verwenden.

Es ist wahrscheinlich eine Frage der Präferenz.

+1

Mit Anwendung meinst du, lassen Xcode das Schema generieren? Oder wird das Schema nur zur Laufzeit erstellt? –

+0

Ich bin mir nicht 100% sicher. Ich möchte sagen, dass es zur Laufzeit generiert wird (ich glaube, dass ein Teil von CoreData init darin besteht, einen Datenspeicher bei Bedarf auf den neuesten Stand zu bringen), aber Sie müssen das überprüfen. –

+0

Xcode wird das Schema nicht generieren. Es ist eine Laufzeitoperation. –

2

Ich glaube nicht, Core Data diese Art von Funktionalität bietet von Natur aus. Wenn ich in Ihren Schuhen wäre, würde ich ein kleines Tool schreiben, das das XML-Parsing durchführen würde, und alles Notwendige tun, um aus diesen Daten das Core Data Model zu erstellen und es bestehen zu lassen. Verschieben Sie dann einfach die sqlite-Datenbank, die Core Data generiert, in Ihr reales Projekt.

Dann schreiben Sie vielleicht einige Codes, die Kopien, die Standarddatenbank in die richtige Position auf dem iPhone, wenn eine Datenbank nicht bereits existieren. Dadurch können Sie auch leicht zu den "sauberen" Daten zurückkehren, wenn Sie sich in einem schlechten Zustand befinden, da Sie einfach die Datenbankdatei löschen und die App erneut ausführen können.

+0

Ich habe tatsächlich etwas genau wie das, was Sie beschrieben, getan, aber anstatt es in zwei Schritten mache ich es in einem. Ich erstelle den .sql-Speicher, wo es im iPhone benötigt wird. Würde dieser Ansatz jedoch nicht zu Problemen führen, wenn es Zeit ist, die App an den App Store zu senden? Wie würden Sie dieses Problem beheben? – Stunner

+0

Warum würde dies Probleme verursachen? Ich denke nicht, dass die Angabe von Seed-Daten mit Ihrer App gegen die Richtlinien des App Store verstößt. –

2

Sie können einen ähnlichen Ansatz verfolgen. Der einfachste Weg besteht wahrscheinlich darin, Ihren Kerndatenverwalteten Kontext einzurichten und dann Ihre XML-Datei einzulesen, indem Sie beim Analysieren der XML-Datei die verwalteten Objekte erstellen.

+0

Dies ist eine gültige Lösung. Allerdings würde ich diese Art des Parsens lieber "offline" machen, so dass die App immer nur eine SQLite-DB-Datei sieht. –

10

Ich bin ein bisschen spät zu dieser Party, aber ich mache etwas ähnliches für GroceryList. Ich habe Daten in Plist-Dateien gespeichert, die ich in meinem CoreData SQLite-Shop brauche. Ich habe ein Befehlszeilen-Fundament-Tool geschrieben, das auf meinem Mac läuft, das die Plist-Dateien analysiert und dann mit meinem Core Data-Objektmodell einen SQLite-Store erstellt. Ich führe dieses Kommandozeilen-Tool als Teil meines Builds (für einige Build-Konfigurationen), so dass ich die Daten nach Belieben neu generieren kann. Um diese Art von Werkzeug in xcode zu erstellen, wählen Sie Datei -> Neues Projekt -> Mac OS X -> Befehlszeilentool und wählen Sie "Kerndaten" aus dem Menü "Typ". Hier ist ein Beispielcode:

#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

Ey Danke fürs Teilen! Jedoch habe ich Probleme beim Bestimmen des MOM-Pfades. Siehe http://stackoverflow.com/questions/4600312/how-to-get-path-of-momd-file-in-core-data Danke! – Stunner

Verwandte Themen