У меня есть 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
, главный контекст переходит к потоковому a 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 не запускает метод делегата после слияния обновления с фоновым потоком
Спасибо заранее.
Edit
Приведенный выше код работал в предыдущей модели. Затем я создал новую модель, копирующую (и вставляя) сущности из предыдущей, и теперь она больше не работает.
Предложения?
Изменить 2
Это предикат, который я использую в NSFetchedResultsController
getter. Это моя вина, но когда я написал сообщение, я не копировал его.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"insertionDate" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
// previous code here
[fetchRequest setSortDescriptors:sortDescriptors];
Теперь о Jody последнем комментарии
В основном() вашего NSOperation вы загружаете новые объекты, а в там похоже, что вы устанавливаете isSync в YES для каждого нового объекта. Предикат, который вы используете для fetchedResultsController, выглядит только для объектов, которые имеют isSync == NO.
Я ожидаю, что, когда свойство isSync
установлено в YES, NSFetchedResultsController
отмечает, что он изменяет и удаляет строки, которые не соответствуют предикату. Я не прав?
Помните, что при слиянии изменений от фона к основному потоку я могу видеть, что несколько объектов обновили их свойство isSync
.