如何制作可以通过关系访问的 mutableArrayValue?

How do I make a mutableArrayValue that I can access through a relationship?

我在我的数据模型中的实体 PersonListItem 之间添加了一个名为 listItems 的对多关系,然后成功地将对象添加到给定的 Person 使用

    let personSelectedListItems = person.mutableSetValue(forKey: "listItems")
    personSelectedListItems.addObjects(from: selectedListItems)
    print("personSelectedListItems after addObjects contains \(personSelectedListItems)")

其中 selectedListItemsListItem 类型的对象数组。打印语句给出:

personSelectedListItems after addObjects contains Relationship 'listItems' on managed object (0x6080000d2050) <PersonMO: 0x6080000d2050> (entity: Person; id: 0xd000000000040002 <x-coredata://1350DE85-4F65-462A-9C36-1EEE3D5298CD/Person/p1> ; data: {
    age = Ky;
    firstName = Uykyu;
    image = <89504e47 0d0a1a0a 0000000d 49484452 000002cc 00000333 08020000 003d00d3 35000000 01735247 4200aece 1ce90000 001c>;
    isVisited = 0;
    lastName = Kuyuy;
    listItems =     (
        "0xd000000005140000 <x-coredata://1350DE85-4F65-462A-9C36-1EEE3D5298CD/ListItem/p325>",
        "0xd000000005680000 <x-coredata://1350DE85-4F65-462A-9C36-1EEE3D5298CD/ListItem/p346>",
        "0xd0000000023c0000 <x-coredata://1350DE85-4F65-462A-9C36-1EEE3D5298CD/ListItem/p143>"
    );
    locationCity = Uyk;
    locationState = You;
    notes = "";
    phoneNumber = "";
    score = nil;
}) with objects {(
    <ListItemMO: 0x6000000b6c20> (entity: ListItem; id: 0xd000000005140000 <x-coredata://1350DE85-4F65-462A-9C36-1EEE3D5298CD/ListItem/p325> ; data: {
    category = Meta;
    isSelected = 1;
    listItem = "Similar values";
    listItemStatus = 1;
    listItemWeight = 1;
    people =     (
        "0xd000000000040002 <x-coredata://1350DE85-4F65-462A-9C36-1EEE3D5298CD/Person/p1>"
    );
}),
    <ListItemMO: 0x6000000af900> (entity: ListItem; id: 0xd000000000080000 <x-coredata://1350DE85-4F65-462A-9C36-1EEE3D5298CD/ListItem/p2> ; data: {
    category = Appearance;
    isSelected = 1;
    listItem = Attractive;
    listItemStatus = 3;
    listItemWeight = 1;
    people =     (
        "0xd000000000040002 <x-coredata://1350DE85-4F65-462A-9C36-1EEE3D5298CD/Person/p1>"
    );
}),
    <ListItemMO: 0x6000000b27e0> (entity: ListItem; id: 0xd0000000023c0000 <x-coredata://1350DE85-4F65-462A-9C36-1EEE3D5298CD/ListItem/p143> ; data: {
    category = Behavior;
    isSelected = 1;
    listItem = "Good grammar";
    listItemStatus = 1;
    listItemWeight = 1;
    people =     (
        "0xd000000000040002 <x-coredata://1350DE85-4F65-462A-9C36-1EEE3D5298CD/Person/p1>"
    );
})
)}

这很好,因为我想为每个 Person 创建这些对象,但这很糟糕,因为它是一个我似乎无法访问的无序集。我希望它是一个可变数组,这样我就可以访问索引处的每个对象,但是当我这样做时

    let personSelectedListItems = person.mutableArrayValue(forKey: "listItems")
    personSelectedListItems.addObjects(from: selectedListItems)
    print("personSelectedListItems after addObjects contains \(personSelectedListItems)")

我收到此错误消息:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'NSManagedObjects of entity 'Person' do not support -mutableArrayValueForKey: for the property 'listItems''

这很令人费解,因为我不知道为什么支持 mutableSetValueForKey: 但不支持数组版本。我真的很想能够通过关系访问对象,最好是通过点表示法。解决此问题的最佳方法是什么?

核心数据对多关系总是由集合表示。对此的部分支持是 NSManagedObject 实现 mutableSetValue(forKey:),这是访问关系的记录方式之一。由于对多关系是集合,NSManagedObject 不支持 mutableArrayValue(forKey:),如该错误消息所示。

如果你想要有序的关系,在数据模型编辑器中标记为有序,然后你就可以使用NSOrderedSet。它仍然不是一个数组,但它确实有顺序。

@Wain 和@TomHarrington 都为我指出了正确的方向,但这是我的问题的答案(经过一些搜索和修改之后):

首先,我需要在我的数据模型文件的数据模型检查器中将一对多关系标记为 'ordered'。第二件事是改变

let personSelectedListItems = person.mutableSetValue(forKey: "listItems")
personSelectedListItems.addObjects(from: selectedListItems)
print("personSelectedListItems after addObjects contains \(personSelectedListItems)")

let personSelectedListItems = person.mutableOrderedSetValue(forKey: "listItems")
personSelectedListItems.addObjects(from: selectedListItems)
print("personSelectedListItems after addObjects contains \(personSelectedListItems)")

这样 mutableOrderedSetValue 就会反映关系的有序性。在那之后,我得到了一套有序的退货。欢呼!但是现在我如何通过关系访问和更改那些单独的对象?这让我想到了第三件事——我不得不将集合向下转换为我的 class(称为 ListItemMO)。抓取有序集合中的第一个对象,然后通过关系改变一个属性,看起来像这样:

    if let listItemSet = personVar.listItems?.object(at: 0) as? ListItemMO {
        listItemSet.listItemStatus = 0
    }