Frage

Ich aktualisiere derzeit eine App, um Core Data zu verwenden.Man könnte sagen, dass die App ein „Datenbank-Viewer“ ist. Es kann jeweils nur eine Datenbank angezeigt werden.Jede Datenbank wird in einem eigenen separaten Ordner gespeichert.Derzeit werden die Daten als Satz von Plist-Dateien heruntergeladen und gespeichert.

In der neuen Version muss ich diese Plist-Datenbanken in Kerndatenspeicher konvertieren (einen Speicher für jede Datenbank). Ich habe bereits die Methoden eingerichtet, mit denen die separaten Speicherdateien erstellt und die Entitäten erstellt werden.Das Problem besteht darin, dass alle Entitäten in der ersten von mir erstellten Datenbank gespeichert werden, nicht in der „aktuellen“ oder „zuletzt erstellten“ Datei.

Der grundlegende Prozess, den ich verwende, ist:

//For each database {
//Create the sqlite file and set up NSManagedObjectContext
[MagicalRecord setupCoreDataStackWithStoreNamed:
    [NSURL fileURLWithPath:
    [NSString stringWithFormat:@"%@/%@/%@.sqlite",
    dirPath, directory, directory]]];
NSManagedObjectContext *managedObjectContext = 
    [NSManagedObjectContext MR_contextForCurrentThread];

//Iterate through all the plist files and create the necessary entities.
//Save new entities to file
[managedObjectContext MR_save];
//Clean up all cashes
[MagicalRecord cleanUp];
}

Wie würde man richtig zwischen Geschäften wechseln und im Wesentlichen alles zwischen jedem Wechsel „zurücksetzen“?Vorzugsweise (wenn möglich) mit Magic Record.

BEARBEITEN:Ich habe einen Teil des Problems herausgefunden und die meisten unerwünschten Verhaltensweisen entfernt.Es stellt sich heraus, dass Sie nicht zuverlässig anrufen können [MagicalRecord cleanUp] in einem Hintergrundthread.Außerdem macht es nicht das, was es meiner Meinung nach tun sollte (siehe unten).Am Ende habe ich nach jedem „Speichern“ den Hauptthread zurückgerufen, um den Core Data-Stack zurückzusetzen.Dadurch wird ein neuer Kontext für die ersten drei Datenbanken erstellt.Danach dupliziert es den Kontext aus der Datenbank vor drei Datenbanken.Es werden also dieselben drei Kontexte in einer Schleife verwendet.

Das ist es, was ich derzeit habe;Ich starte den Prozess, indem ich einen Hintergrundthread erstelle und den Code ausführe, um eine einzelne Datenbank im Hintergrund zu erstellen:

backgroundQueue = dispatch_queue_create("com.BrandonMcQuilkin.myQueue", NULL);
    dispatch_async(backgroundQueue, ^(void) {
        [self createSQLiteDatabase:updateList];
    });

Dann den Stack und die Datenbank erstellen:

- (void)createSQLiteDatabase:(NSArray *)updateList
{
    NSString *directory = [updateList objectAtIndex:0];
    [MagicalRecord setupCoreDataStackWithStoreNamed:
        [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@/%@.sqlite",
        dirPath, directory, directory]]];
    NSManagedObjectContext *managedObjectContext = 
        [NSManagedObjectContext MR_contextForCurrentThread];
    //Check to see if the stack has reset
    NSLog(@"Before:%i", [[Competition MR_findAllInContext:managedObjectContext] count]);

    //Create and add entities to context...

    //Prepare for next loop
    NSLog(@"After:%i", [[Competition MR_findAllInContext:managedObjectContext] count]);
    [managedObjectContext MR_saveNestedContexts];
    [NSManagedObjectContext MR_resetContextForCurrentThread];

    NSMutableArray *temp = [[NSMutableArray alloc] initWithArray:updateList];
    [temp removeObjectAtIndex:0];

    dispatch_async(dispatch_get_main_queue(), ^(void){
        [self shouldContinueUpdating:temp];
    });

Dann alles zurücksetzen und für alle Datenbanken wiederholen:

- (void)shouldContinueUpdating:(NSArray *)databases
{
    //preform cleanup on main thread and release background thread
    [MagicalRecord cleanUp];
    dispatch_release(backgroundQueue);

    if ([databases count] != 0) {
        backgroundQueue = dispatch_queue_create("com.BrandonMcQuilkin.myQueue", NULL);
        dispatch_async(backgroundQueue, ^(void) {
            [self createSQLiteDatabase:databases];
        });
    }
}

Mit den beiden NSLogs erhalte ich Folgendes in der Konsole:(Bei Verwendung von sechs Datenbanken ist das Muster dasselbe, egal wie viele Datenbanken ich konvertiere.)

//First Loop
Before:0
After:308
//Second Loop
Before:0
After:257
//Third Loop
Before:0
After:37
//Fourth Loop
Before:308 
After:541 
//Fifth Loop
Before:257
After:490
//Sixth Loop
Before:37
After:270
... Keep adding to each of the three contexts.

Und [MagicalRecord cleanUp] tut nicht das, was es angeblich tut.Hier ist, was die Methode tun soll.

+ (void) cleanUpStack;
{
[NSManagedObjectContext MR_cleanUp];
[NSManagedObjectModel MR_setDefaultManagedObjectModel:nil];
[NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:nil];
[NSPersistentStore MR_setDefaultPersistentStore:nil];
}

Aber es stellt sich heraus, dass der NSStoreCoordinator jedes Mal, wenn ich speichere, derselbe Koordinator am selben Speicherort ist und jeder Speicher herumhängt.Etwas funktioniert nicht richtig...

War es hilfreich?

Lösung 2

Es stellt sich heraus, dass das Problem, das ich habe, auf einen Fehler in MagicalRecord zurückzuführen ist.Ich habe hier ein Git-Problem eingereicht: https://github.com/magicalpanda/MagicalRecord/issues/270

Andere Tipps

MagicalRecord ist für Sie möglicherweise nicht das beste Tool für diesen Job ...

Korrigieren wir zunächst Ihre Verwendung von setupCoreDataStackWithStoreNamed:Methode.Der Parameter akzeptiert einen NSString, keine URL und keinen Dateipfad.MagicalRecord wählt den richtigen Weg für Sie und erstellt dort Ihren Shop.Ihre resultierende SQLite-Datei wird wahrscheinlich mit dem Pfad benannt, den Sie beabsichtigt haben.

Als Nächstes müssen Sie Ihr CoreData-Modell für diese Datei dynamisch erstellen.Das ist etwas schwierig, aber möglich.Sie müssen diese Plist-Dateien durchlaufen, Entitäten, Attribute und Beziehungen interpretieren, entsprechende NSEntityDescriptions, NSAttributeDescriptions und NSRelationshipDesctiptions erstellen und ein NSManagedObjectModel „manuell“ füllen.Sie werden nach der Methode suchen wollen

- [NSManagedObjectModel setEntities:(NSArray *)]

sowie die Erstellungsmethoden für NSEntityDescription, NSAttributeDescription und NSRelationshipDescription.

Sie sollten dieses Modell auch irgendwo speichern, damit Sie es nicht jedes Mal neu erstellen müssen.Glücklicherweise entspricht es NSCoding, sodass Sie es einfach auf der Festplatte speichern können.

Danach möchten Sie wahrscheinlich Ihre Daten füllen.Von hier aus kann MagicalRecord Ihnen helfen.Ich schlage vor, einen Blick auf die zu werfen Datenimport leicht gemacht Blogbeitrag, für den ich geschrieben habe Kakao ist meine Freundin

Wenn Sie „den Speicher wechseln“ möchten, was meiner Meinung nach bedeutet, dass Sie für jede vorhandene Plist-Datei einen neuen Speicher erstellen möchten, müssen Sie den gesamten Core Data-Stack für jede Datei entfernen.Wenn Sie es schaffen, MagicalRecord für dieses Projekt zu verwenden, müssen Sie sich [MagicalRecord cleanUp] ansehen und von vorne beginnen.Wenn jedes Modell gleich wäre, könnten Sie damit auskommen, Ihren Persistent Store Coordinator freizugeben und einen neuen für Ihren Shop zu erstellen.Aber da Ihre „Schemata“ wahrscheinlich anders sein werden, möchten Sie einfach alles neu streichen und von vorne beginnen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top