访问核心数据中的子对象时出现关系错误

Posted

技术标签:

【中文标题】访问核心数据中的子对象时出现关系错误【英文标题】:Getting relationship fault while accessing a child object in core data 【发布时间】:2017-07-25 09:43:46 【问题描述】:

我有两个核心数据实体ContactGroup。组有两个属性 existingUsersnonExistingUsers 类型为 Contact 和 toMany 关系

我正在尝试使用groupId 作为谓词来获取组属性。这就是我获取组详细信息的方式

let requestForGroups = NSFetchRequest<NSFetchRequestResult>(entityName: "Group")
    requestForGroups.returnsObjectsAsFaults = false
    requestForGroups.predicate = NSPredicate(format: "groupId == %@", (groupObject?.groupId)!)
    requestForGroups.relationshipKeyPathsForPrefetching = ["existingUsers", "nonExistingUsers"]
    do 
        let results = try managedObjectContext.fetch(requestForGroups) as! [Group]
        if results.count > 0 
            print(results.first)
            var group: Group!
            group = results.first
            for users in group.existingUsers?.allObjects as! [Contact] 
                print(users)
            
            for users in group.nonExistingUsers?.allObjects as! [Contact] 
                print(users)
            
        
     catch let error as NSError 
        print("Error: \(error) " +
            "description \(error.localizedDescription)")

当我尝试打印Group 对象时,出现以下关系错误

Optional(<Foodvite.Group: 0x1706801e0> (entity: Group; id: 0xd0000000018c0000 <x-coredata://E4C6CB69-7192-435C-9E2A-534FCFC563F5/Group/p99> ; data: 
existingUsers = "<relationship fault: 0x17063b620 'existingUsers'>";
groupCategory = nil;
groupIconUrl = nil;
groupId = "8ba3e576-edf7-41fa-abd9-df80c4c693f2";
groupName = Friends;
groupOwnerId = "7fa49a4e-2cbf-4c77-8868-bc97ad89881b";
nonExistingUsers = "<relationship fault: 0x17063b600 'nonExistingUsers'>";
))

有人可以建议一种访问existingUsersnonExistingUsers 数据的方法吗?

【问题讨论】:

试试print(existingUsers!.first?.&lt;#some property#&gt;) existingUsers 的类型为 NSSet。它没有first 属性 公平点,但是 NSSet 的 allObjects 属性返回 Array 【参考方案1】:

这是正确的,因为默认情况下 Coredata 关系是延迟加载的。

这里是 Apple documentation。

托管对象通常表示保存在持久存储中的数据。 在某些情况下,托管对象可能是错误的——一个对象 尚未从外部数据存储加载属性值。 故障减少了您的应用程序消耗的内存量。

要访问existingUsersnonExistingUsers 数据,您需要明确询问(如果它们不是数组):

print(group!.existingUsers.<attributeName>)
print(group!.nonExistingUsers.<attributeName>)

如果你的关系是数组:

if let first = group?.existingUsers.first 
    print(first.<attributeName>)

阅读this 以获得更好的理解。

【讨论】:

我仍然遇到同样的故障错误。您能否建议另一种访问数据的方法? @Aark:你什么时候得到故障错误?在控制台中处于调试模式时?还是打印(results.first)? 我收到了Print(results.first)Print(group!.existingUsers) 的故障错误。这是在尝试打印 group.existingUsers Optional(Relationship 'existingUsers' fault on managed object (0x17068e060) (entity: Group; id: 0xd000000001f00000 ;数据:existingUsers = ""; 尝试获取现有用户的属性,如果它是一个数组,您可能需要先访问它的元素。我正在编辑我的答案.. existingUsers 的类型为 NSSet。它没有first 属性【参考方案2】:

错误不是错误。这是一个性能考虑,除非您确实需要它,否则不会加载来自持久存储的数据。对于具有表示与潜在 数千 个其他实体的一对多关系的属性的获取对象尤其如此。如果您甚至不打算使用它们,那么在内存中加载数千个其他对象是很愚蠢的。

在您的情况下,existingUsersnonExistingUsers 可能都是 NSSet。您可以像这样访问其中的元素:

//assuming "group" is an NSManagedObject

for user in group.existingUsers! 
    user.property = someValue
    if user.otherProperty == ...

在访问existingUsers 集合中的每个user 时,NSManagedObjectContext 将使用从持久存储中检索到的值自动填充对象的属性。简而言之,每个user 的属性的预期值将在您访问或分配它们时正确返回/设置。

【讨论】:

以上是关于访问核心数据中的子对象时出现关系错误的主要内容,如果未能解决你的问题,请参考以下文章

向核心数据添加记录时出现 NSSet 错误(多对多关系)

访问共享进程内存时出现分段错误(核心转储)

使用工具提示时出现错误 #2025:提供的 DisplayObject 必须是调用者的子对象

尝试访问向量中对象中的字段时出现段错误

尝试获取关系中的数据时出现 Symfony 错误

加入两个包含 SUM() 函数的子查询时出现无效操作错误