Можно ли сохранить контекст управляемого объекта из блока завершения в NSOperation? - PullRequest
1 голос
/ 05 октября 2011

Мое приложение использует Core Data и NSOperationQueue. В соответствии с рекомендациями Apple, я создаю отдельный контекст управляемого объекта для каждой очереди. В моем случае это довольно просто: у меня есть одна фоновая очередь, которая выполняет всю тяжелую работу, и другая в основном потоке, который просто читает данные.

Казалось бы, для меня имеет смысл сделать что-то вроде этого:

  • В фоновой очереди создайте операцию, выполняющую кучу работы в контексте управляемого объекта.
  • Добавьте к этой операции блок завершения, сохраняющий контекст управляемого объекта.

Но я прочитал в документации NSOperation:

Точный контекст выполнения для вашего блока завершения не гарантируется, но обычно является вторичным потоком. Следовательно, вы не должны использовать этот блок для выполнения какой-либо работы, которая требует очень определенного контекста выполнения. Вместо этого вы должны перенести эту работу на основной поток вашего приложения или на конкретный поток, который способен это сделать.

Конечно, важно, чтобы это сохранение выполнялось из того же потока, который «владеет» контекстом управляемого объекта. Но я не всегда понимаю, относится ли «поток» к очередям операций или нет. (Иногда он используется более или менее определенным образом.)

Работает ли моя стратегия «блока завершения»?

1 Ответ

1 голос
/ 05 октября 2011

Сделайте небольшой трюк, чтобы решить эту проблему в любом месте кода: Создать МОК:

    moc = [[NSManagedObjectContext alloc] init];
    [moc setUndoManager:nil];
    [moc setPersistentStoreCoordinator:coordinator];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(importerDidSave:) name:NSManagedObjectContextDidSaveNotification object:self.moc];

не забудьте удалить наблюдателя:

- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:self.moc];
[moc release];
[super dealloc];
}

и, наконец, проверьте, прежде чем объединить изменения, если это основной поток:

- (void)importerDidSave:(NSNotification *)saveNotification {
NSLog(@"MERGE in client controller");
if ([NSThread isMainThread]) {
    [self.mainMoc mergeChangesFromContextDidSaveNotification:saveNotification];

} else {
    [self performSelectorOnMainThread:@selector(importerDidSave:) withObject:saveNotification waitUntilDone:NO];
}
}
...