如果谓词使用 IN,则不会调用 NSFetchedResultsControllerDelegate 方法?
Posted
技术标签:
【中文标题】如果谓词使用 IN,则不会调用 NSFetchedResultsControllerDelegate 方法?【英文标题】:NSFetchedResultsControllerDelegate methods not being called if its predicate use IN? 【发布时间】:2010-07-02 16:52:18 【问题描述】:我正在结合 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页)。 如果需要,我可以在这里发布。
【问题讨论】:
【参考方案1】:解决了将对象 ID 替换为 NSManagedObject
到谓词中的问题。
之前:[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 上进行测试。
【讨论】:
谢谢!我还遇到了一个问题,即没有调用 FRC 代表,虽然这是一个不同的问题,但结果证明是我的谓词有问题。以上是关于如果谓词使用 IN,则不会调用 NSFetchedResultsControllerDelegate 方法?的主要内容,如果未能解决你的问题,请参考以下文章
如果 ExceptionHandler 捕获到异常,则不会调用 DelegatingHandler