Я реализую UITableViewController в сочетании с NSFetchedResultsController.Когда создается экземпляр UITableViewController, создается NSFetchedResultsController (по существу, аналогично примеру CoreDataBooks ) с другим предикатом, основанным на выборе, который пользователь сделал на предыдущем контроллере.
Иногда я устанавливаю предикат ввот так:
predicate = [NSPredicate predicateWithFormat:@"container = %@", aManagedObject];
иногда так:
predicate = [NSPredicate predicateWithFormat:@"container IN (%@)", aNSMutableSetOfObjectsID];
Оба предиката работают нормально, потому что они правильно выбирают все мои объекты, как и ожидалось.Проблема возникает, когда я пытаюсь вставить новый управляемый объект в список, когда задан второй предикат.Фактически в этом случае методы делегата FRC никогда не вызываются, поэтому представление таблицы не обновляется автоматически.
Я уверен, что новый объект правильно добавлен в тот же контекст, который используется FRC, и что его отношение «контейнер»установить так, чтобы делегат был запущен, но это не так!
Что я пробовал:
Я говорю, что второй предикат работает нормально, потому что если ядобавьте новый объект, а затем вытолкните UITableViewController и нажмите его снова, заставив все данные быть повторно загруженными, новый объект появится в списке без проблем.
Другой мой тест - принудительно пересчитать FRC сразу после новогообъект добавлен:
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
exit(-1);
}
[self.tableView reloadData];
новый объект отображается правильно.
Код:
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController == nil) {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSManagedObjectContext *managedObjectContext = realEstate.managedObjectContext;
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Item" inManagedObjectContext:managedObjectContext]];
[fetchRequest setPredicate:[self getBasePredicate]];
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name"
ascending:YES
selector:@selector(localizedCaseInsensitiveCompare:)];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:nameDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[nameDescriptor release];
[sortDescriptors release];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:@"sectionIndex"
cacheName:nil];
self.fetchedResultsController = aFetchedResultsController;
fetchedResultsController.delegate = self;
[aFetchedResultsController release];
[fetchRequest release];
}
return fetchedResultsController;
}
// return a predicate for the fetchedResultsController
- (NSPredicate *)getBasePredicate {
NSPredicate *predicate = nil;
if ([[managedObject valueForKey:@"subcontainersCount"] intValue] == 0)
// container without sons **(FIRST PREDICATE)**
predicate = [NSPredicate predicateWithFormat:@"container = %@", managedObject];
else {
// container with sons **(SECOND PREDICATE)**
predicate = [NSPredicate predicateWithFormat:@"container IN (%@)", [Container allDescendantsObjectID:(Container *)managedObject includeSource:YES]];
}
return predicate;
}
- (void)addNewItem {
Item *newItem = (Item *)[NSEntityDescription insertNewObjectForEntityForName:@"Item"
inManagedObjectContext:realEstate.managedObjectContext];
newItem.name = @"my new item";
newItem.container = aContainerManagedObject;
NSError *error = nil;
if (![realEstate.managedObjectContext save:&error]) {
abort();
}
}
Используемые мной методы NSFetchedResultsControllerDelegate:взято из "Больше iPhone 3 Разработка".Полный код см. здесь (стр. 30-31, 35).
Я могу опубликовать здесь при необходимости.