Вопрос

В настоящее время я обновляю приложение для использования Core Data.Можно сказать, что приложение представляет собой «просмотрщик баз данных», одновременно можно просматривать только одну базу данных.Каждая база данных хранится в отдельной папке.В настоящее время данные загружаются и сохраняются в виде набора файлов plist.

В новой версии мне нужно преобразовать эти базы данных plist в хранилища Core Data (по одному хранилищу для каждой базы данных). Я уже настроил методы, которые создают отдельные файлы хранилища и создают объекты.Проблема в том, что все объекты сохраняются в первой созданной мной базе данных, а не в «текущем» или «последнем созданном» файле.

Основной процесс, который я использую:

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

Как правильно переключаться между магазинами, по сути «сбрасывая» все между каждым переключением?Предпочтительно (если возможно) с помощью магической записи.

РЕДАКТИРОВАТЬ:Я обнаружил часть проблемы и устранил большую часть нежелательного поведения.Оказывается, надежно позвонить нельзя [MagicalRecord cleanUp] в фоновом потоке.Кроме того, он не делает того, что, по моему мнению, должен (см. ниже).В итоге я перезванивал в основной поток после каждого «сохранения», чтобы сбросить стек основных данных.При этом создается новый контекст для первых трех баз данных.после этого он дублирует контекст из базы данных трех баз данных назад.Таким образом, в цикле используются одни и те же три контекста.

Это то, что у меня есть сейчас;Я начинаю процесс с создания фонового потока и запускаю код для создания единой базы данных в фоновом режиме:

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

Затем создаем стек и базу данных:

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

Затем сбросьте все и повторите для всех баз данных:

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

С двумя NSLogs я получаю это в консоли:(при использовании шести баз данных шаблон будет одинаковым независимо от того, сколько баз данных я конвертирую.)

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

И [MagicalRecord cleanUp] не делает того, что говорит.Вот что должен делать этот метод.

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

Но оказывается, что NSStoreCoordinator каждый раз, когда я сохраняю, является одним и тем же координатором, в одной и той же ячейке памяти, и каждое хранилище висит поблизости.Что-то работает не так...

Это было полезно?

Решение 2

Оказывается, проблема, с которой я столкнулся, связана с ошибкой в ​​MagicalRecord.Я представил проблему git здесь: https://github.com/magicalpanda/MagicalRecord/issues/270

Другие советы

MagicalRecord может оказаться для вас не лучшим инструментом для этой работы...

Во-первых, давайте исправим использование setupCoreDataStackWithStoreNamed:метод.Параметр принимает NSString, а не URL-адрес или путь к файлу.MagicalRecord выберет для вас подходящий путь и создаст там ваш магазин.результирующий файл sqlite, скорее всего, будет назван по тому пути, который вы задумали.

Далее вам нужно будет динамически создать модель CoreData для этого файла.Это довольно сложно, но возможно.Вам нужно будет просмотреть эти файлы plist, интерпретировать сущности, атрибуты и отношения, а также создать соответствующие NSEntityDescriptions, NSAttributeDescriptions и NSRelationshipDesctiptions и заполнить NSManagedObjectModel «вручную».Вы захотите найти метод

- [NSManagedObjectModel setEntities:(NSArray *)]

а также методы создания NSEntityDescription, NSAttributeDescription и NSRelationshipDescription.

Вы также захотите сохранить где-нибудь эту модель, чтобы вам не приходилось каждый раз воссоздавать ее.К счастью, он соответствует NSCoding, поэтому вы сможете сохранить его на диск.

После этого вы, вероятно, захотите заполнить свои данные.Здесь вам может помочь MagicalRecord.Предлагаю посмотреть Импорт данных стал проще сообщение в блоге, для которого я написал Какао — моя подруга

Если вы хотите «переключить хранилище», что, я думаю, означает, что вы хотите создать новое хранилище для каждого имеющегося у вас файла plist, тогда вам придется разрушить весь стек Core Data для каждого файла.Если вам удастся использовать MagicalRecord для этого проекта, вам нужно будет просмотреть [MagicalRecord cleanUp] и начать все сначала.Если бы все модели были одинаковыми, вы могли бы обойтись выпуском постоянного координатора магазина и созданием нового для вашего магазина.Но поскольку ваши «схемы», вероятно, будут другими, вам просто захочется все поцарапать и начать заново.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top