Question

Je suis actuellement en train de mettre à jour une application pour utiliser Core Data.L'application que l'on pourrait dire est une "visionneuse de base de données", une seule base de données peut être consultée à la fois.Chaque base de données est conservée dans son propre dossier séparé.Actuellement, les données sont téléchargées et stockées sous forme d'un ensemble de fichiers plist.

Dans la nouvelle version, je dois convertir ces bases de données plist en magasins Core Data (un magasin pour chaque base de données.) J'ai déjà configuré les méthodes qui créent les fichiers de magasin séparés et créent les entités.Le problème est que toutes les entités sont enregistrées dans la première base de données que j'ai créée, et non dans le fichier "actuel" ou "dernièrement créé".

Le processus de base que j'utilise est le suivant :

//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];
}

Comment basculer correctement entre les magasins, essentiellement en « réinitialisant » tout entre chaque commutateur.De préférence (si possible) en utilisant un enregistrement magique.

MODIFIER:J'ai découvert une partie du problème et supprimé la plupart des comportements indésirables.Il s'avère que vous ne pouvez pas appeler de manière fiable [MagicalRecord cleanUp] sur un fil de fond.De plus, il ne fait pas ce que je pense qu'il devrait (voir ci-dessous).J'ai fini par rappeler le thread principal après chaque "sauvegarde" pour réinitialiser la pile Core Data.Cela crée un nouveau contexte pour les trois premières bases de données.après cela, il duplique le contexte de la base de données il y a trois bases de données.Ainsi, les trois mêmes contextes sont utilisés dans une boucle.

C'est ce que j'ai actuellement ;Je démarre le processus en créant un thread en arrière-plan et j'exécute le code pour créer une seule base de données en arrière-plan :

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

Puis création de la pile et de la base de données :

- (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];
    });

Ensuite, réinitialisez tout et répétez pour toutes les bases de données :

- (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];
        });
    }
}

Avec les deux NSLogs, j'obtiens ceci dans la console :(en utilisant six bases de données, le modèle est le même quel que soit le nombre de bases de données que je convertis.)

//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.

Et [MagicalRecord cleanUp] ne fait pas ce qu'il prétend faire.Voici ce que la méthode est censée faire.

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

Mais il s'avère que NSStoreCoordinator, à chaque fois que j'enregistre, est le même coordinateur, dans le même emplacement mémoire, et chaque magasin traîne.Quelque chose ne fonctionne pas correctement...

Était-ce utile?

La solution 2

Il s'avère que le problème que j'ai est dû à un bug dans MagicalRecord.J'ai soumis un problème git ici : https://github.com/magicalpanda/MagicalRecord/issues/270

Autres conseils

MagicalRecord n'est peut-être pas le meilleur outil pour ce travail pour vous...

Tout d’abord, corrigeons votre utilisation de setupCoreDataStackWithStoreNamed :méthode.Le paramètre prend une NSString, pas une URL, ni un chemin de fichier.MagicalRecord choisira le chemin qui vous convient et y créera votre boutique.votre fichier sqlite résultant sera probablement nommé avec le chemin que vous vouliez qu'il soit.

Ensuite, vous devrez créer dynamiquement votre modèle CoreData pour ce fichier.C'est un peu difficile, mais possible.Vous devrez parcourir ces fichiers plist, interpréter les entités, les attributs et les relations, créer les NSEntityDescriptions, NSAttributeDescriptions et NSRelationshipDesctiptions correspondantes et remplir un NSManagedObjectModel "manuellement".Vous voudrez chercher la méthode

- [NSManagedObjectModel setEntities:(NSArray *)]

ainsi que les méthodes de création pour NSEntityDescription, NSAttributeDescription et NSRelationshipDescription.

Vous souhaiterez également enregistrer ce modèle quelque part afin de ne pas avoir à le recréer à chaque fois.Heureusement, il est conforme à NSCoding, vous devriez donc simplement pouvoir le sauvegarder sur le disque.

Après cela, vous souhaiterez probablement remplir vos données.À partir de là, MagicalRecord peut vous aider.Je suggère de regarder le Importer des données en toute simplicité article de blog pour lequel j'ai écrit Le cacao est ma petite amie

Si vous souhaitez "changer de magasin", ce qui signifie, je suppose, que vous souhaitez créer un nouveau magasin pour chaque fichier plist que vous avez, vous devrez alors supprimer toute la pile Core Data pour chaque fichier.Si vous parvenez à utiliser MagicalRecord pour ce projet, vous devrez consulter [MagicalRecord cleanUp] et recommencer.Si chaque modèle était le même, vous pourriez vous contenter de libérer votre coordinateur de magasin persistant et d'en créer un nouveau dans votre magasin.Mais comme vos « schémas » seront probablement différents, vous aurez juste envie de tout effacer et de recommencer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top