У меня есть NSFetchedResultsController
и несколько операций обновляют управляемые объекты в отдельных потоках через NSOperationQueue
.
FRC (со своим предикатом )выглядит следующим образом.:
- (NSFetchedResultsController*)fetchedResultsController
{
if(fetchedResultsController) return fetchedResultsController;
NSManagedObjectContext* mainContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Check" inManagedObjectContext:mainContext]];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"isSync == %@", [NSNumber numberWithBool:NO]]];
[fetchRequest setFetchBatchSize:10];
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:mainContext sectionNameKeyPath:nil cacheName:nil];
fetchedResultsController.delegate = self;
[fetchRequest release], fetchRequest = nil;
return fetchedResultsController;
}
Основной поток и потоковая операция имеют свои собственные контексты управляемых объектов. У них только один и тот же координатор.
В поточной операции я изменяю свойство isSync
с NO
на YES
. Чтобы узнать, какой объект Check
нужно обновить, основной контекст передается многопоточному NSManagedObjectID
. Потоковая операция извлекает управляемый объект следующим образом::
-(void)main
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSManagedObjectContext *exportContext = [[NSManagedObjectContext alloc] init];
[exportContext setPersistentStoreCoordinator:[self persistentStoreCoordinator]];
//...
Check* check = (Check*)[exportContext existingObjectWithID:objID error:&error];
check.isSync = [NSNumber numberWithBool:YES];
//...
[exportContext save:&error];
[pool release], pool = nil;
}
Когда потоковая операция вызывает save
, вызывается уведомление mergeChangesFromContextDidSaveNotification
, и основной контекст объединяет изменения.
- (void)contextChanged:(NSNotification*)notification
{
if ([notification object] == [self managedObjectContext]) return;
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(contextChanged:) withObject:notification waitUntilDone:YES];
return;
}
[[self managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];
}
Регистрация описания notification
приводит к проверке правильности выполнения изменений.
Моя проблема
Методы делегатов NSFetchedResultsControllerDelegate
не вызываются.
Это довольно странно, поскольку, имея дело с одним и тем же контекстом,основной, позволяет прослушивать изменения и вызывать методы делегатов, например. удаление объекта строки в UITableView
.
Я нашел несколько тем на SO с той же проблемой. Я испробовал все обходные пути, но не могу найти ценного решения.:
NSFetchedResultsController не показывает обновления из других контекстов
NSFetchedResultsController не запускает метод делегата после слияния обновления из фонового потока
Заранее спасибо.
Изменить
Приведенный выше код работал в предыдущей модели. Затем я создал новую модель, скопировав (и вставив объекты )из предыдущей, и теперь она больше не работает.
Предложения?
Редактировать 2
Это предикат, который я использую в NSFetchedResultsController
геттере. Это моя вина, но когда я писал пост, я его не скопировал.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"insertionDate" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
// previous code here
[fetchRequest setSortDescriptors:sortDescriptors];
Теперь о Джоди последний комментарий
В основном ()вашего NSOperation вы загружаете новые объекты, а в там похоже, что вы устанавливаете isSync на YES для каждого нового объекта. Предикат, который вы используете для fetchedResultsController, ищет только для объектов, у которых isSync == NO.
Я ожидаю, что когда для свойства isSync
задано значение YES, NSFetchedResultsController
замечает, что изменяет и удаляет строки, не соответствующие предикату. Я ошибся?
Помните, что при объединении изменений из фона в основной поток я вижу, что несколько объектов обновили свое свойство isSync
.