Core data 使用NSFetchedResultsController进行多对多NSPredicate
根据数据模型配置创建NSPredicate对象时遇到问题 我有两个实体,一个叫鲍勃,一个叫弗雷德。Bob与Fred有一种称为“hasFreds”(反面是hasBobs)的多对多关系,Fred有一个类型为BOOL的HasEat属性 我想取一份Bob的名单,每个Bob至少有一个Fred,haseat=YES。如果没有带有haseat=YES的FRED,我想返回所有没有FRED的BOB 这就是我到目前为止所拥有的,它不太有效(它不符合“如果没有带haseat的Fred=是,我想返回所有不带Fred的BOB”条件):Core data 使用NSFetchedResultsController进行多对多NSPredicate,core-data,many-to-many,nspredicate,nsfetchedresultscontroller,Core Data,Many To Many,Nspredicate,Nsfetchedresultscontroller,根据数据模型配置创建NSPredicate对象时遇到问题 我有两个实体,一个叫鲍勃,一个叫弗雷德。Bob与Fred有一种称为“hasFreds”(反面是hasBobs)的多对多关系,Fred有一个类型为BOOL的HasEat属性 我想取一份Bob的名单,每个Bob至少有一个Fred,haseat=YES。如果没有带有haseat=YES的FRED,我想返回所有没有FRED的BOB 这就是我到目前为止所拥有的,它不太有效(它不符合“如果没有带haseat的Fred=是,我想返回所有不带Fred的B
我认为从概念的角度来看,你的条件并不是一个真正的问题。您需要进行两个查询,一个基于另一个查询的结果。这并不是SQL查询的真正目的,更不用说对象图谓词了 因此,我认为最简单、最直观的解决方案应该是使用两个版本的“获取结果”控制器 您可以通过动态更改谓词来创建另一个版本。(我经常使用这种模式,例如用于搜索。)因为子查询无论如何都会导致多次访问持久存储,所以在为获取的结果控制器设置谓词之前,您可以只进行一次有效的获取以评估条件 设置谓词后,如有必要,请将其删除:
if ([context countForFetchRequest:request] == 0) {
request.predicate = nil;
}
// continue creating your FRC with the request
请注意,countForFetchRequest
非常高效,不占用内存
要更新
self.fetchedResultsController = nil;
[self.tableView reloadData]; // or collection view
如果您需要利用FRC的缓存功能,那么按照上述模式使用两个独立FRC的解决方案也是可行的。多亏了用户Mundi,我才能够想出一个解决方案。首先是实现一个名为getCorrectPredicate的方法
-(NSPredicate *)getCorrectPredicate{
NSPredicate *predicate1;
NSFetchRequest *fr;
predicate1 = [NSPredicate predicateWithFormat:
@"(SUBQUERY(hasFreds, $fred, $fred.hasEaten = %@).@count > 0)",@YES];
fr = [NSFetchRequest fetchRequestWithEntityName:@"Bob"];
fr.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:NO selector:@selector(compare:)]];
fr.predicate = predicate1;
if([[[self appDelegate] managedObjectContext] countForFetchRequest:fr error:nil] == 0){
// we have a none situation
self.predicateState = [NSPredicate predicateWithFormat:
@"hasFreds.@count=0"];
}else{
self.predicateState = predicate1;
}
return self.predicateState;
}
第二个是检查NSFetchedResultsController委托方法controllerDidChangeContent中的谓词是否更改
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller{
[_expensesTable endUpdates];
[[[self frc] fetchRequest] setPredicate:[self getCorrectPredicate]];
[self performFetch];
}
我用你的解决方案想出了一个类似的解决方案。在controllerDidChangeContent中,我使用countForFetchRequest检查是否需要切换谓词,然后根据需要进行更改。我通过告诉NSFetchedResultsController执行蚀刻并重新开始来跟踪更改。我会记下你的答案,因为它确实帮了我很多忙。嗯,基本上是相同的解决方案,所以你应该接受这个答案。只是FRC的交付机制略有不同——这并不是解决方案的关键点。
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller{
[_expensesTable endUpdates];
[[[self frc] fetchRequest] setPredicate:[self getCorrectPredicate]];
[self performFetch];
}