NSFetchedResultsControllerDelegate методы, не вызываемые, если его предикат использует IN? - PullRequest
3 голосов
/ 02 июля 2010

Я реализую 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).
Я могу опубликовать здесь при необходимости.

1 Ответ

2 голосов
/ 03 июля 2010

Решена замена идентификатора объекта на NSManagedObject в предикате.

До: [NSPredicate predicateWithFormat:@"container IN (%@)", aNSMutableSetOfObjectsID];

После: [NSPredicate predicateWithFormat:@"container IN (%@)", aNSMutableSetOfNSManagedObject];

По некоторым причинам делегат FRC не вызывается, если предикат выбирает объекты, используя ID вместо точных NSManagedObjects.
Я тестирую на iPhoneOS 3.1.3 и 3.2. Однако iPhoneOS 4.0 должна поддерживать и objectsID, и NSManagedObject и правильно вызывать методы делегата FRC, но я пока не могу протестировать 4.0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...