Ответ 1
Вы можете получить доступ к контекстам одним из двух способов:
- В потоке/очереди. Это относится к ограниченным контекстам и контекстам основной очереди. Вы можете получить доступ к ним свободно из собственного потока.
- С
-performBlock:
, если это контекст частной очереди или если вы касаетесь контекста из потока, отличного от того, к которому он принадлежит.
Вы не можете использовать dispatch_async
для доступа к контексту. Если вы хотите, чтобы действие было асинхронным, вам нужно использовать -performBlock:
.
Если вы использовали один контекст раньше, и вы касались его с помощью dispatch_async
, вы нарушали правило ограничения потока.
Update
При вызове [[NSManagedObjectContext alloc] init]
, функционально эквивалентном [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType]
.
NSManagedObjectContext
имеет всегда поток.
Что касается выполнения нескольких методов, вы можете просто вызвать их все в одном блоке:
NSManagedObjectContext *moc = ...;
[moc performBlock:^{
//Fetch something
//Process data
//Save
}];
Или вы можете вложить их, если хотите, чтобы они были все асинхронны друг от друга:
NSManagedObjectContext *moc = ...;
[moc performBlock:^{
//Fetch Something
[moc performBlock:^{
//Process Data
}];
[moc performBlock:^{
//Save
}];
}];
Так как -performBlock:
безопасен для повторного входа, вы можете вложить их все, что хотите.
Обновить Async save
Чтобы выполнить сохранение async, у вас должно быть два контекста (или более):
- Контекст главной очереди, с которым пользовательский интерфейс взаимодействует с
- Контекст частной очереди, который сохраняет
Частный контекст имеет NSPersistentStoreCoordinator
, а основной контекст очереди имеет закрытый как родительский.
Вся работа выполняется в контексте основной очереди, и вы можете безопасно ее сохранять, обычно в основном потоке. Это спасение будет мгновенным. После этого вы выполните сохранение async:
NSManagedObjectContext *privateMOC = ...;
NSManagedObjectContext *mainMOC = ...;
//Do something on the mainMOC
NSError *error = nil;
if (![mainMOC save:&error]) {
NSLog(@"Main MOC save failed: %@\n%@", [error localizedDescription], [error userInfo]);
abort();
}
[privateMOC performBlock:^{
NSError *error = nil;
if (![privateMOC save:&error]) {
NSLog(@"Private moc failed to write to disk: %@\n%@", [error localizedDescription], [error userInfo]);
abort();
}
}];
Если у вас уже есть приложение, все, что вам нужно сделать, это:
- Создайте свой собственный moc
- Установите его как родительский элемент основного
- Измените основной init
- Добавить метод сохранения частного блока при каждом вызове save на основном
Вы можете реорганизовать оттуда, но это все, что вам действительно нужно изменить.