使用 fetched 属性的核心数据跨存储查询
Posted
技术标签:
【中文标题】使用 fetched 属性的核心数据跨存储查询【英文标题】:Core data cross-store query using fetched property 【发布时间】:2013-10-21 06:37:15 【问题描述】:背景
我有一个由两个存储组成的核心数据数据库(一个存储我的数据,一个存储用户数据),它们之间通过获取的属性链接。
假设我有两个实体,它们之间的关系是 0 到 1。 卡 0 ----> 1 卡状态
1) 卡片,包含参考数据和一些属性(externalKey、word、description...)
获取属性 - userData(指向 CardStatus 并使用 externalKey 做两个实体之间的链接)
2) CardStatus,包含每张卡片的状态。该实体存储在用户数据存储中。
在某些情况下,我需要根据卡片的状态获取卡片(例如:检索所有标记为过期的卡片、检索所有标记为新的卡片等...)
问题
我应该编写什么样的谓词来根据 CardStatus 实体的值获取 Card 实体?
我尝试在谓词中直接使用我获取的属性 userData,但核心数据不允许这样做。
由于未捕获的异常而终止应用程序 'NSInvalidArgumentException',原因:'keypath userData not found in 实体'
然后我尝试使用子查询(见下文) - 仍然无法正常工作。有趣的是,当我直接在 NSArray(而不是获取请求)上进行过滤时,它工作得很好。
示例 - 检索具有特定状态的卡:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SUBQUERY(userData, $x, ($x.currentLevel == 0)).@count > 0)"];
示例 - 检索标记为新的卡片(即 CardStatus 中没有数据):
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SUBQUERY(SELF, $x, $x.userData.@count == 0).@count > 0"];
有什么建议吗?
【问题讨论】:
【参考方案1】:我找到了解决办法。
查询是正确的,现在工作正常。问题是我在线程中使用了一个子 managedObjectContext,而这些子上下文似乎不接受使用获取的属性。
我通过(简单地)直接基于我的持久存储创建一个新的托管对象上下文来替换它(换句话说,这个上下文和我在主线程中使用的上下文在层次结构中处于同一级别)。
以下是说明我所描述内容的代码:
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSManagedObjectContext *child = [[NSManagedObjectContext alloc] init];
[child setPersistentStoreCoordinator:[appDelegate.managedObjectContext persistentStoreCoordinator]];
现在一切正常。
【讨论】:
【参考方案2】:在我看来,CardStatus 实体可以作为某种枚举来补充动态数据存储的逻辑。我认为这不是跨商店获取的好案例。增加不必要的复杂性似乎有点矫枉过正。
相反,您可以将状态作为普通属性直接存储在 Card 实体中,可能是数字格式。如有必要,您可以使用跨存储获取从静态存储中获取状态名称。
【讨论】:
您好 Mundi,感谢您的反馈。拥有单独存储的目的是能够轻松地将参考数据与用户数据分离。该应用程序将存储大量数据(它是一个抽认卡应用程序,因此它将包含大量单词 + 大量列表),我需要能够将新内容推送给用户,而无需繁琐的迁移脚本...... . 我明白了——但是卡的状态绝对应该不存储在静态持久存储中,你不同意吗? 是的,你是对的 - 我的问题并不清楚。 CardStatus 是用户数据存储的一部分。我已将缺少的描述添加到我的问题中。总结一下:“Card”属于参考存储,“CardStatus”属于用户数据存储。以上是关于使用 fetched 属性的核心数据跨存储查询的主要内容,如果未能解决你的问题,请参考以下文章
使用 apollo 缓存调用一次存储的 fetch API?