【问题标题】: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

标签: ios swift core-data


【解决方案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 的属性的预期值将在您访问或分配它们时正确返回/设置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 1970-01-01
    • 2012-12-30
    相关资源
    最近更新 更多