CoreData :NSFetchedResultsController 一对多对多的关系
Posted
技术标签:
【中文标题】CoreData :NSFetchedResultsController 一对多对多的关系【英文标题】:CoreData :NSFetchedResultsController one to many to many to many relationship 【发布时间】:2015-06-02 00:01:04 【问题描述】:我在开发应用程序时使用的是核心数据,核心数据对象如下所示:
给出剧院名称和流派名称我想显示演员名称。任何人都知道构建NSPredicate
的方法吗?
【问题讨论】:
模型似乎关闭了。电影有戏院,戏院有电影。应该是直接关系。电影有类型,但剧院没有类型。 (不是剧院是喜剧,而是电影。) @PetahChristian 影院,类型关系只是对每个影院的电影进行分类的方式 我了解,但与现实世界的关系不符。如果有人在寻找喜剧,他们会想看看什么电影是喜剧,而不是什么剧院是喜剧。 (剧院可能放映一部喜剧电影,但剧院本身不是喜剧。)人们想知道剧院正在播放什么电影,但没有直接关系。这就是我要说的。您正在使简单请求的谓词变得更复杂,就像这个 Actors 问题必须通过 Genres 一样,而该查询与 Genres 无关。 【参考方案1】:您可以使用 SUBQUERY 构建深入“对多”关系的 NSPredicate:
// Set predicate
NSPredicate *requestPredicate = [NSPredicate predicateWithFormat:@"SUBQUERY(genres, $g, ANY $g.movies.name == %@).@count != 0", @"Batman vs Superman"];
[fetchRequest setPredicate:requestPredicate];
更新
根据您更新的示例,您需要这样的嵌套子查询:
NSPredicate *requestPredicate = [NSPredicate predicateWithFormat:@"SUBQUERY(movies, $m, ANY $m.genres.name == %@).@count != 0 AND SUBQUERY(movies, $m, SUBQUERY($m.genres, $g, ANY $g.theaters.name == %@).@count != 0).@count != 0", @"Action", @"Harkins"];
这是一个示例 Cast 实体提取:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Cast" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO];
NSArray *sortDescriptors = @[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
// Set predicate
NSPredicate *requestPredicate = [NSPredicate predicateWithFormat:@"SUBQUERY(movies, $m, ANY $m.genres.name == %@).@count != 0 AND SUBQUERY(movies, $m, SUBQUERY($m.genres, $g, ANY $g.theaters.name == %@).@count != 0).@count != 0", @"Action", @"Harkins"];
[fetchRequest setPredicate:requestPredicate];
// Fetch
NSError *error = nil;
if (![aFetchedResultsController performFetch:&error])
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
// Check fetched objects
NSArray *fetchedObjects = [aFetchedResultsController fetchedObjects];
for (Cast *eachCast in fetchedObjects)
NSLog(@"Each Cast name: %@", eachCast.name);
只需将@"Action" 替换为所需的流派名称,将@"Harkins" 替换为剧院名称。
以下是我设置核心数据模型的方法:
【讨论】:
感谢您的解决方案,但在您的解决方案中,您正在根据电影名称进行查询。例如,在我原来的问题中。我有电影院名称“西雅图”和流派名称“科幻”。我想列出所有在影院放映的电影的所有演员类型(西雅图/科幻)。 根据您的示例更新了我的答案。 @user2924482 你能用嵌套的子查询获得过滤的Actor吗?以上是关于CoreData :NSFetchedResultsController 一对多对多的关系的主要内容,如果未能解决你的问题,请参考以下文章
CoreData(iOS):是不是需要创建数据库才能使用CoreData?coredata可以对简单的平面文件进行操作吗? [关闭]
CoreData与CloudKit同步时将图像保存到CoreData?