如何在复杂的 Core Data 模型中高效访问数据

Posted

技术标签:

【中文标题】如何在复杂的 Core Data 模型中高效访问数据【英文标题】:How to efficiently access data in complex Core Data model 【发布时间】:2014-05-07 00:08:24 【问题描述】:

我的 Xcode 项目中有一个相当复杂的核心数据模型。为简单起见,我在这里只说我的模型包括与 Teams 有一对多关系的 Games,每个 Teams 与 Players 有一对多关系。所有这三个实体也都有自己的属性(例如,gameLocation、teamScore、playerNumber 等)。

由于 Restkit 向 Ruby on Rails 构建的网站发出的大量 GET 请求,我的数据库已完全填充。所以现在,我想开始处理这些数据——显示和修改它。我知道这涉及获取请求和谓词,但我不知道何时何地需要执行这些获取。我可以获取一个游戏,然后从该游戏中访问与该游戏相关的所有内容吗?例如,这是我获取今天安排的所有游戏的代码:

NSFetchRequest *request = [[NSFetchRequest alloc] init];

NSEntityDescription *desc = [NSEntityDescription entityForName:@"Game" inManagedObjectContext:self.managedObjectContext];
[request setEntity:desc];

NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"time" ascending:YES];
[request setSortDescriptors:@[sort]];

/*** some code that determines the values for variables 'todaysDate' and 'tomorrowsDate' ***/

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(date >= %@) AND (date < %@)", todaysDate, tomorrowsDate];
[request setPredicate:predicate];

NSError *error = nil;
self.games = [self.managedObjectContext executeFetchRequest:request error:&error];

但是现在呢?访问这些游戏的团队的最佳方式是什么?我需要更多获取请求还是效率低下?我试过这样的东西,但它似乎不对

Game *game1 = [self.games objectAtIndex:0];
NSMutableSet *game1Teams = [game1 mutableSetValueForKey:@"gameTeams"];

不仅是球队,我如何获得这些比赛球队的分数?那些游戏的玩家?等等……

(也许参考教程或一些示例代码对我来说是个好地方,因为我确信这是微不足道的东西)

【问题讨论】:

【参考方案1】:

关键词是这样的:

“我可以获取一个游戏,然后从该游戏中访问与该游戏相关的所有内容吗?”

答案是“是”。

您可以基于单个获取请求遍历整个“树”,只需引用指向实体中定义的集合(或其他)的指针,并允许 Core Data 在需要加载各种实体时进行处理。

一开始这对我来说毫无意义,但是当我放弃战斗时,我发现它比我想象的要容易得多。

这是我的一个项目:

@property (nonatomic, retain) NSString * goalName;
@property (nonatomic, retain) NSData * goalPicture;
@property (nonatomic, retain) NSNumber * indexOrder;
@property (nonatomic, retain) NSNumber * wordPicture;
@property (nonatomic, retain) NSSet *item;
@property (nonatomic, retain) User *user;
@property (nonatomic, retain) NSSet *video;

在我的例子中,用户是树中的***节点,每个目标下可以有多个项目以及多个视频。

一旦我为给定用户完成了获取请求,我就可以使用用户实体中的 NSSet 访问该用户的目标。所以,我得到了一组目标:

NSSet *goals = userObj.goal;
Goal *g = [goals anyObject]; // for example.

然后,如果我希望将项目“包含”在给定目标中:

NSSet *items = g.items;
Item *i = [items anyObject];

等等。重要的是核心数据将有效地加载实体。如果您有 10,000 个项目附加到某个特定目标,那么您不必担心那些在真正需要它们之前会被获取...

【讨论】:

是的!这正是我想要做的。我只是不知道该怎么做。如何在将 NSArray 游戏作为实例变量的视图控制器中获取游戏中的团队? 您有 [set anyObject] 但我没有看到该 set 已定义(不应编译)。我认为它需要是 [game1Teams anyObject]。这对我来说看起来不错,但我可能会遗漏一些东西...... 我玩了一会儿,让它开始工作。感谢您的帮助!【参考方案2】:

这个链接对你有用

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreData/cdProgrammingGuide.html

具体来说,故障是您似乎要问的问题。就引用而言(例如,对来自球队的球员列表的引用),核心数据不会获取整个数据集。相反,它有一个叫做故障的东西。然后,当您尝试访问玩家(例如 [team.players objectAtIndex:10] 或其他)时,CoreData 将匆匆离开并获取该对象的实际数据。

了解这一点,以及如何以及何时将对象转回故障以清理内存应该有助于回答您的问题。

【讨论】:

以上是关于如何在复杂的 Core Data 模型中高效访问数据的主要内容,如果未能解决你的问题,请参考以下文章

Core Data 错误地选择了映射模型

如何在 iPhone 应用程序之间共享一个 Core Data 模型?

如何在 Core Data 中创建数据模型?

Core Data 中的异步对象构造

如何防止在 ASP.NET Core 的 Razor 视图 HTML 中禁用或只读输入字段的模型绑定?

如何清除和重置 Core Data 数据模型