首页 文章

如何在Swift中定义CoreData关系?

提问于
浏览
12

在CoreData中,我定义了从 NodeTag 的无序to-many关系 . 我已经创建了一个像这样的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'终止应用程序,原因:'to-many关系的值不可接受的类型:property =“tags”;期望的类型= NSSet;给定type = _TtCSs22ContiguousArrayStorage000000000B3440D4; value =(“<_TtC8MotorNav3Tag:0xb3437b0>(entity:Tag; id:0xb343800; data:)”) . '

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

4 回答

  • 16

    为了能够在Swift中使用一对多关系,您需要将属性定义为:

    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)
    

    Important: 要使一切正常,您应该验证CoreData模型中实体的类名是否包含您的模块名称 . 例如 . MyProjectName.Node

  • 9

    从Xcode 7和Swift 2.0开始,release note 17583057指出:

    NSManaged属性可以与方法和属性一起使用,以访问Core Data自动生成的符合键值编码的多个访问器 .

    @NSManaged var employees: NSSet
    
    @NSManaged func addEmployeesObject(employee: Employee)
    @NSManaged func removeEmployeesObject(employee: Employee)
    @NSManaged func addEmployees(employees: NSSet)
    @NSManaged func removeEmployees(employees: NSSet)
    

    这些可以在NSManagedObject子类中声明 . (17583057)

    所以你只需声明以下方法,CoreData将负责其余的工作:

    @NSManaged func addTagsObject(tag: Tag)
    @NSManaged func removeTagsObject(tag: Tag)
    @NSManaged func addTags(tags: NSSet)
    @NSManaged func removeTags(tags: NSSet)
    
  • 12

    实际上你可以定义:

    @NSManaged var employees: Set<Employee>
    

    并直接使用 Setinsertremove 方法 .

  • 0

    基于@Kenenle的答案,如果你想要厚颜无耻,能够说出来

    node.tags.append(tag)
    

    可以将调用包装到self.mutableSetValueForKey:

    class Node: NSManagedObject {
    
        var tags: NSMutableOrderedSet {
            return self.mutableOrderedSetValueForKey("tags")
        }
    }
    

相关问题