Cocoa touch 如何切换UITableView';NSFetchedResultsController(或其谓词)是否以编程方式?
我有一个UITableView,它显示了大量名为“Documents”的实体的子集。子集由另一个实体“Selection”定义。选择是命名的、有序的文档列表 它工作正常,除非我想在运行时更改显示的选择。我只有一张空白名单 基本上,我需要更改NSFetchedResultsController持有的谓词,以便新谓词使用另一个选择。我不能让它工作。我的最后一次尝试是完全摆脱NSFetchedResultsController并重新分配它:Cocoa touch 如何切换UITableView';NSFetchedResultsController(或其谓词)是否以编程方式?,cocoa-touch,uitableview,core-data,nsfetchedresultscontroller,master-detail,Cocoa Touch,Uitableview,Core Data,Nsfetchedresultscontroller,Master Detail,我有一个UITableView,它显示了大量名为“Documents”的实体的子集。子集由另一个实体“Selection”定义。选择是命名的、有序的文档列表 它工作正常,除非我想在运行时更改显示的选择。我只有一张空白名单 基本上,我需要更改NSFetchedResultsController持有的谓词,以便新谓词使用另一个选择。我不能让它工作。我的最后一次尝试是完全摆脱NSFetchedResultsController并重新分配它: - (void) displaySelection:(Sel
- (void) displaySelection:(Selection *)aSet
{
self.currentSelection = aSet;
self.fetchedResultsController = nil;
// methods here don't all use the property but directly the ivar, so we must trigger the getter
[self fetchedResultsController];
[self.tableView reloadData];
}
当然,NSFetchedResultsController getter做了正确的事情:
- (NSFetchedResultsController *)fetchedResultsController
{
if (fetchedResultsController != nil) { return fetchedResultsController; }
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"DocInSelection" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"selection.identifier like %@", currentSelection.identifier];
[fetchRequest setPredicate:predicate];
<snip>
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
<snip>
return fetchedResultsController;
}
-(NSFetchedResultsController*)fetchedResultsController
{
如果(fetchedResultsController!=nil){return fetchedResultsController;}
NSFetchRequest*fetchRequest=[[NSFetchRequest alloc]init];
NSEntityDescription*entity=[NSEntityDescription entityForName:@“DocInSelection”在managedObjectContext:managedObjectContext中];
[FetchRequestSetEntity:entity];
NSPredicate*谓词=[NSPredicate谓词格式:@“selection.identifier like%@”,currentSelection.identifier];
[FetchRequestSetPredicate:谓词];
[FetchRequestSetSortDescriptors:sortDescriptors];
NSFetchedResultsController*aFetchedResultsController=[[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@“Root”];
aFetchedResultsController.delegate=self;
self.fetchedResultsController=aFetchedResultsController;
返回获取的ResultsController;
}
此代码第一次起作用,因为已设置初始选择。但是,当调用displaySelection:
时,tableview变为空白
会议上提出了一个非常类似的问题
答案是摆脱NSFetchedResultsController。我不想这样做,因为NSFetchedResultsController在这里带来了很多有用的东西(例如缓存、部分加载…)。问题仍然存在:如何在NSFetchedResultsController支持的UITableView中“切换”数据,其中“切换”意味着具有不同的谓词,甚至(在我的情况下)具有不同的实体
请注意,出于完整性的考虑,由于从选择到文档的多对多关系是有序的,因此它通过称为DocInSelection的中间轻量级实体进行处理,该实体具有“ordering”属性以及与文档和选择的两个多对一关系
谢谢你的建议。在我发布我的问题后,我尝试了另一个问题的OP所显示的代码的变体。它对我有用。这是:
- (void) displaySelection:(Selection *)aSet
{
if (aSet != self.currentSelection) {
self.currentSelection = aSet;
NSFetchRequest *fetchRequest = [[self fetchedResultsController] fetchRequest];
NSPredicate *predicate = nil;
NSEntityDescription *entity = nil;
entity = [NSEntityDescription entityForName:@"DocInSelection" inManagedObjectContext:managedObjectContext];
predicate = [NSPredicate predicateWithFormat:@"selection.identifier like %@", currentSelection.identifier];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:predicate];
[NSFetchedResultsController deleteCacheWithName:@"Root"];
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
[self.tableView reloadData];
}
由于NSFetchedResultsController(FRC)是一个对象,因此可以像存储任何其他对象一样存储它的实例 一种有用的技术是初始化多个FRC并将其存储在字典中,然后将tableview控制器的
fetchedResultController
属性设置为当前需要的FRC。这在某些情况下非常有用,例如使用分段控件对同一表中的不同属性或实体进行排序。这种技术的优点是可以维护单个FRC缓存,从而显著加快抓取速度
只需确保在交换控制器之前向tableview本身发送一个
beginUpdates
,然后在交换完成后发送一个endUpdates
。这样可以防止在交换FRC时,表格在狭窄的窗口中请求数据。然后调用reloadData
虽然这可能有效,但iOS参考库中有一条注释让我感到困扰:
重要提示:您不能修改
获取请求。例如,你必须
不更改其谓词或排序
订单
资料来源:
iOS 3.2参考库中不存在此附加说明
我只是想指出这一点。一个重要的注意事项:如果“覆盖”fetchController对象,请确保首先清除其.delegate-否则在删除行时会崩溃,等等,因为旧的fetchController及其委托会获得事件。啊!有趣。由于选择集取决于用户操作,因此对我来说,这可能不是一个正确的想法。不过我会记住的。谢谢。既然UICollectionView没有相应的方法,你会如何在它上进行beginUpdate/EndUpdate?我没有注意到这一点。如果我们能从苹果那里得到一个解释,那将是最好的。我有点理解它:由于FetchedResultController保留其获取结果,因此从其脚下拉出fetchRequest地毯可能会导致不一致。这就是为什么上面的代码片段1-清除缓存,2-再次执行获取请求,3-要求tableView重新加载其数据。现在看来还可以,但我想有一些正式的说法。如果每次都要删除CacheWithName:@“Root”,为什么还要创建缓存呢。如果不使用缓存,请传入一个缓存名nil。尽管缓存是使用NSFRC的一个好处。我认为,虽然当前选择(可能很大)保持不变,但是
NSFetchedResultController
使用缓存的效果很好。“每一次”可能不是那么频繁。此外,苹果在“如果您正在使用缓存,请将其删除(使用deleteCacheWithName:)”。苹果还添加了“如果您正在更改获取请求,通常不应使用缓存”。测试应该有助于确定缓存在这里是否有益。