Дочерний контекст не заполняет изменения в контексте по умолчанию (MagicalRecord)

Я экспериментировал с той же проблемой, описанной здесь. Проблема заключается в том, что при использовании дочернего MOC контекста DEFAULT для сохранения в coredata 90% случаев результаты в контексте основного потока обновляются с изменениями, исходящими от дочернего MOC, но иногда это не так.

В своих тестах я неоднократно писал одни и те же сущности (не слишком быстро, используя пользовательский интерфейс): рекламную сущность (fav__count) и любимые отношения между рекламой и пользователем.

При сохранении из дочернего MOC контекста DEFAULT это ожидаемый вывод MagicalRecord (я также напечатал счет обновленных объектов):

[__52-[ZCServer postFavoriteAd:withDelegate:andSelector:]_block_invoke_2]↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓  POST FAVORITE  ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
2013-09-19 11:40:35.154  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb8b55e0) → Saving <NSManagedObjectContext (0xb8b55e0): *** UNNAMED ***> on *** BACKGROUND THREAD ***
2013-09-19 11:40:35.155  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb8b55e0) → Save Parents? 1
2013-09-19 11:40:35.155  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb8b55e0) → Save Synchronously? 1
2013-09-19 11:40:35.155  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb8b55e0) → Updated objects = 4
2013-09-19 11:40:35.183  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xba72700) → Saving <NSManagedObjectContext (0xba72700): *** DEFAULT ***> on *** BACKGROUND THREAD ***
2013-09-19 11:40:35.184  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xba72700) → Save Parents? 1
2013-09-19 11:40:35.184  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xba72700) → Save Synchronously? 1
2013-09-19 11:40:35.185  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xba72700) → Updated objects = 2
2013-09-19 11:40:35.188 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3f7740) → Saving <NSManagedObjectContext (0xa3f7740): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
2013-09-19 11:40:35.189 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3f7740) → Save Parents? 1
2013-09-19 11:40:35.189 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3f7740) → Save Synchronously? 1
2013-09-19 11:40:35.189 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3f7740) → Updated objects = 2
2013-09-19 11:40:35.191 __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke29(0xa3f7740) → Finished saving: <NSManagedObjectContext (0xa3f7740): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
[__52-[ZCServer postFavoriteAd:withDelegate:andSelector:]_block_invoke672] ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ------*------ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑

** Примечание: дочерний MOC регистрирует 4 обновления, но в этом случае обновляются два объекта (метаданные изображений) с одинаковой информацией.

Но иногда это вывод получен (без обновленных объектов для родителей):

[__52-[ZCServer postFavoriteAd:withDelegate:andSelector:]_block_invoke_2]↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓  POST FAVORITE  ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
2013-09-19 11:37:39.718  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb876d20) → Saving <NSManagedObjectContext (0xb876d20): *** UNNAMED ***> on *** BACKGROUND THREAD ***
2013-09-19 11:37:39.718  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb876d20) → Save Parents? 1
2013-09-19 11:37:39.719  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb876d20) → Save Synchronously? 1
2013-09-19 11:37:39.719  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb876d20) → Updated objects = 4
2013-09-19 11:37:39.720  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xba72700) → Saving <NSManagedObjectContext (0xba72700): *** DEFAULT ***> on *** BACKGROUND THREAD ***
2013-09-19 11:37:39.720  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xba72700) → Save Parents? 1
2013-09-19 11:37:39.720  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xba72700) → Save Synchronously? 1
2013-09-19 11:37:39.721  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xba72700) → Updated objects = 0
2013-09-19 11:37:39.722 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3f7740) → Saving <NSManagedObjectContext (0xa3f7740): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
2013-09-19 11:37:39.723 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3f7740) → Save Parents? 1
2013-09-19 11:37:39.723 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3f7740) → Save Synchronously? 1
2013-09-19 11:37:39.723 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3f7740) → Updated objects = 0
2013-09-19 11:37:39.725 __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke29(0xa3f7740) → Finished saving: <NSManagedObjectContext (0xa3f7740): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
[__52-[ZCServer postFavoriteAd:withDelegate:andSelector:]_block_invoke672] ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ------*------ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑

Я использую последовательную очередь для выполнения ВСЕХ операций записи в CoreData. Эта последовательная очередь создает дочерний MOC для текущего потока. Это код для писателя:

+ (void) saveWithBlock: (void(^)(NSManagedObjectContext *threadContext))block
{
    [ZCMagicalRecord saveWithBlock:block completion:nil];

}

+ (void) saveWithBlock: (void(^)(NSManagedObjectContext *threadContext))block completion:(MRSaveCompletionHandler)completion;
{
    dispatch_async( _queue, ^{

        NSManagedObjectContext *ctx = [NSManagedObjectContext MR_contextForCurrentThread];

        [ctx performBlockAndWait:^{
            block( ctx );

            [ctx  MR_saveWithOptions:MRSaveParentContexts|MRSaveSynchronously completion:completion];
        }];

    });
}

С другой стороны, когда я использую [MagicalRecord saveUsingCurrentThreadContextWithBlock:] используя UI MainThread, изменения ВСЕГДА заполняются в контекст ROOT и в постоянное хранилище:

[__52-[ZCServer postFavoriteAd:withDelegate:andSelector:]_block_invoke_2]↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓  POST FAVORITE  ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
2013-09-19 11:47:01.082 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb348550) → Saving <NSManagedObjectContext (0xb348550): *** DEFAULT ***> on *** MAIN THREAD ***
2013-09-19 11:47:01.082 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb348550) → Save Parents? 1
2013-09-19 11:47:01.083 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb348550) → Save Synchronously? 0
2013-09-19 11:47:01.083 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb348550) → Updated objects = 5
2013-09-19 11:47:01.102 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3cd840) → Saving <NSManagedObjectContext (0xa3cd840): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
2013-09-19 11:47:01.102 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3cd840) → Save Parents? 1
2013-09-19 11:47:01.103 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3cd840) → Save Synchronously? 0
2013-09-19 11:47:01.103 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3cd840) → Updated objects = 2
2013-09-19 11:47:01.106  __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke29(0xa3cd840) → Finished saving: <NSManagedObjectContext (0xa3cd840): *** BACKGROUND SAVING (ROOT) ***> on *** BACKGROUND THREAD ***
[__52-[ZCServer postFavoriteAd:withDelegate:andSelector:]_block_invoke676] ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ------*------ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑

Код для [MagicalRecord saveUsingCurrentThreadContextWithBlock:] похоже на то, что я написал (я только написал это, чтобы сделать все записи последовательно):

+ (void) saveUsingCurrentThreadContextWithBlockAndWait:(void (^)(NSManagedObjectContext *localContext))block;
{
    NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];

    [localContext performBlockAndWait:^{
        if (block) {
            block(localContext);
        }

        [localContext MR_saveWithOptions:MRSaveParentContexts|MRSaveSynchronously completion:nil];
    }];
}

Пока я делал этот тест, в CoreData не было другого вида записей. Я разместил здесь пример POST FAVORITE, но между сообщениями было выполнено DELETE FAVORITE, и в сообщениях происходит случайная ошибка в сообщениях и удалениях. Ответ сервера также был проверен правильно.

НОТА

Контекст объекта, передаваемый в блоки кода, игнорируется. Я всегда использую [EntityClass MR_CreateEntity] который использует фактический контекст потока. И контекст, используемый в MR_saveWithOptions:completion: allways это контекст потока, который выполняет блок. Таким образом, один и тот же контекст используется во всех операциях. Приложение очень сложное и отлично работает в большинстве случаев, но эта ошибка может создать больше проблем, чем я сейчас не вижу.

0 ответов

Другие вопросы по тегам