我正在与NSFetchedResultsController一起实现一个UITableViewController。
实例化UITableViewController时,NSFetchedResultsController的构造(与CoreDataBooks示例基本相同)具有不同的谓词,基于用户在前一个控制器上做出的选择。
有时候我会用这种方式设置谓词:
predicate = [NSPredicate predicateWithFormat:@"container = %@", aManagedObject];
有时以这种方式:
predicate = [NSPredicate predicateWithFormat:@"container IN (%@)", aNSMutableSetOfObjectsID];
两个谓词都可以正常工作,因为它们可以按预期正确获取所有对象。 当我尝试在设置第二个谓词时将新的托管对象插入列表时,会出现问题。事实上,在这种情况下,FRC委托方法永远不会被调用,因此tableview不会自动更新 我确定新对象被正确地添加到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开发”。完整的代码可以参见here(第30-31,35页) 如果需要,我可以在这里发帖。
答案 0 :(得分:2)
解决了将带有NSManagedObject
的对象ID替换为谓词的问题。
之前:[NSPredicate predicateWithFormat:@"container IN (%@)", aNSMutableSetOfObjectsID];
之后:[NSPredicate predicateWithFormat:@"container IN (%@)", aNSMutableSetOfNSManagedObject];
由于某些原因,如果谓词使用ID而不是精确的NSManagedObjects获取对象,则不会调用FRC委托。
我正在测试iPhoneOS 3.1.3和3.2。但是,iPhoneOS 4.0应该同时支持objectsID和NSManagedObject并正确调用FRC委托方法,但我现在无法在4.0上进行测试。