Как создать дочерний NSManagedObjectContext?

Я видел несколько видео/потоков, которые говорят, что можно создать "дочерние" MOC - MOC, которые используют другие MOC как их постоянные магазины. Полезно, например, в контексте, где вы выполняете потоковую обработку своего приложения, и хотите иметь один главный MOC, который может сохранять/откатывать изменения, которые создают дочерние потоки. (Из того, что я понимаю, MOC и его managedObjects ДОЛЖНЫ все использоваться в одном потоке)

Вопрос в том, как мне создать дочерний MOC? Я не могу отследить видеоролики WWDC, которые я наблюдал, которые их вводили, и все, что я видел, говорит о том, как их использовать, ТОЛЬКО они сделаны. Я могу легко выделить новый MOC, но как его установить постоянный магазин будет другим MOC? Ссылка не показывает никаких функций, которые это делают!

Ответ 1

Создайте новый MOC, для которого вы полностью контролируете синхронизацию. Это то же самое, что и вызов init и такое же поведение, как отношения между родителями и дочерними элементами.

NSManagedObjectContext *moc = [[NSManagedObjectContext alloc]
       initWithConcurrencyType:NSConfinementConcurrencyType];

Вы родите MOC другому MOC, установив его свойство:

moc.parentContext = someOtherMocThatIsNowMyParent;

Здесь ребенок выбирает родителя. Я уверен, что мои дети хотят, чтобы они были NSManagedObjectContexts. Родительский контекст должен быть либо NSPrivateQueueConcurrencyType, либо NSMainQueueConcurrencyType.

Вы можете создать MOC, привязанный к частной очереди:

NSManagedObjectContext *moc = [[NSManagedObjectContext alloc]
       initWithConcurrencyType:NSPrivateQueueConcurrencyType];

что означает, что вы должны получить доступ к нему только через API performBlock или performBlockAndWait. Вы можете вызвать эти методы из любого потока, поскольку они обеспечат правильную сериализацию кода в блоке. Например...

NSManagedObjectContext *moc = [[NSManagedObjectContext alloc]
       initWithConcurrencyType:NSPrivateQueueConcurrencyType];
moc.parentContext = someOtherMocThatIsNowMyParent;
[moc performBlock:^{
    // All code running in this block will be automatically serialized
    // with respect to all other performBlock or performBlockAndWait
    // calls for this same MOC.
    // Access "moc" to your heart content inside these blocks of code.
}];

Разница между performBlock и performBlockAndWait заключается в том, что performBlock создаст блок кода и запланирует его с помощью Grand Central Dispatch, который будет выполняться асинхронно в будущем в неизвестном потоке. Вызов метода немедленно вернется.

performBlockAndWait выполнит некоторую магическую синхронизацию со всеми другими вызовами performBlock, и когда все блоки, которые были представлены до этого, будут выполнены, этот блок будет выполнен. Вызывающий поток будет отложен до завершения этого вызова.

Вы также можете создать MOC, привязанный к основному потоку, точно так же, как частный concurrency.

NSManagedObjectContext *moc = [[NSManagedObjectContext alloc]
       initWithConcurrencyType:NSMainQueueConcurrencyType];
moc.parentContext = someOtherMocThatIsNowMyParent;
[moc performBlock:^{
    // All code running in this block will be automatically serialized
    // with respect to all other performBlock or performBlockAndWait
    // calls for this same MOC.  Furthermore, it will be serialized with
    // respect to the main thread as well, so this code will run in the
    // main thread -- which is important if you want to do UI work or other
    // stuff that requires the main thread.
}];

что означает, что вы должны обращаться к нему напрямую, если знаете, что находитесь в основном потоке, или с помощью API performBlock или performBlockAndWait.

Теперь вы можете использовать "main concurrency" MOC либо с помощью методов performBlock, либо напрямую , если, вы знаете, что вы уже работаете в основном потоке.

Ответ 2

Инициализируйте дочерний MOC, затем:

[_childMOC performBlockAndWait:^{
            [_childMOC setParentContext:parentMOC]; 
 }];