一尘不染

如何在Swift中定义CoreData关系?

swift

在CoreData中,我定义了从Node到无序的多对多关系Tag。我创建了一个这样的Swift实体:

import CoreData
class Node : NSManagedObject {
    @NSManaged var tags : Array<Tag>
}

现在,我要向Tag的实例添加Node,如下所示:

var node = NSEntityDescription.insertNewObjectForEntityForName("Node", inManagedObjectContext: managedObjectContext) as Node
node.tags.append(tag)

但是,此操作失败并显示以下错误:

由于未捕获的异常“ NSInvalidArgumentException”而终止应用程序,原因:“一对多关系的值的不可接受类型:property =“
tags”; 所需的类型= NSSet ; 给定类型=
_TtCSs22ContiguousArrayStorage000000000B3440D4; 值=(“
<_TtC8MotorNav3Tag:0xb3437b0>(实体:Tag; id:0xb343800; data:{…})”)。

一对多关系的正确类型是什么?


阅读 218

收藏
2020-07-07

共1个答案

一尘不染

为了能够在Swift中处理一对多关系,您需要将property定义为:

class Node: NSManagedObject {
    @NSManaged var tags: NSSet
}

如果您尝试使用NSMutableSet更改,则不会保存在CoreData中。当然,建议在以下位置定义反向链接Node

class Tag: NSManagedObject {
    @NSManaged var node: Node
}

但是Swift仍然无法在运行时生成动态访问器,因此我们需要手动定义它们。在类中定义它们extension并放入Entity+CoreData.swift文件中非常方便。波纹管是Node+CoreData.swift文件的内容:

extension Node {
    func addTagObject(value:Tag) {
        var items = self.mutableSetValueForKey("tags");
        items.addObject(value)
    }

    func removeTagObject(value:Tag) {
        var items = self.mutableSetValueForKey("tags");
        items.removeObject(value)
    }
}

用法:

// somewhere before created/fetched node and tag entities
node.addTagObject(tag)

重要说明: 要使其全部正常工作,您应该验证CoreData模型中实体的类名称包括模块名称。例如MyProjectName.Node

2020-07-07