Core data 如何在Swift中定义CoreData关系?

Core data 如何在Swift中定义CoreData关系?,core-data,swift,ios8,Core Data,Swift,Ios8,在CoreData中,我定义了从节点到标记的无序到多的关系。我创建了这样一个Swift实体: import CoreData class Node : NSManagedObject { @NSManaged var tags : Array<Tag> } var node = NSEntityDescription.insertNewObjectForEntityForName("Node", inManagedObjectContext: managedObjectCo

在CoreData中,我定义了从
节点到
标记的无序到多的关系。我创建了这样一个Swift实体:

import CoreData
class Node : NSManagedObject {
    @NSManaged var tags : Array<Tag>
}
var node = NSEntityDescription.insertNewObjectForEntityForName("Node", inManagedObjectContext: managedObjectContext) as Node
node.tags.append(tag)
但是,此操作失败,并出现以下错误:

由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“to-many关系的值类型不可接受:property=“tags”;所需类型=NSSet;给定类型=_TtCSs22ContiguousArrayStorage000000000B3440D4;值=( “(实体:标记;id:0xb343800;数据:{…})” ).'


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

要在Swift中处理一对多关系,您需要将属性定义为:

class Node: NSManagedObject {
    @NSManaged var tags: NSSet
}
如果尝试使用
NSMutableSet
更改将不会保存在CoreData中。当然,建议在
节点中定义反向链接:

class Tag: NSManagedObject {
    @NSManaged var node: Node
}
但Swift仍然无法在运行时生成动态访问器,因此我们需要手动定义它们。在class
extension
中定义它们并将其放入
Entity+CoreData.swift
文件中非常方便。下面是
节点+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

以@Keenle的答案为基础,如果你想变得厚颜无耻、简洁,并且能够说

node.tags.append(tag)
可以将调用包装为self.mutableSetValueForKey:

class Node: NSManagedObject {

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

截至Xcode 7和Swift 2.0,17583057声明:

NSManaged属性既可以与方法一起使用,也可以与 属性,用于访问自动生成的核心数据 键值编码兼容许多访问器

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

因此,您只需声明以下方法,CoreData将处理其余方法:

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

实际上,您可以定义:

@NSManaged var employees: Set<Employee>
@NSManaged var employees:Set

并直接使用
集合
插入
删除
方法。

NSSet在Swift中不可用?您在哪里找到的?错误消息还表明关系是有序的,而不是无序的。@BryanChen啊,是的,您的评论使我意识到NSSet可以通过
Foundation
@MartinR获得。我复制了错误消息,它仍然被定义为有序集。@bouke:错误消息仍然提到".. “ordered to many relationship”的值。能否请您将实际的错误消息复制/粘贴到问题中,以避免将来读者的混淆?嘿,Keenie,当我使用您的扩展名时,我得到错误:
“'NSSet'没有名为'addTagObject'的成员”“
。你知道我可能做错了什么吗?@Pirijan,你必须在tags:NSSet属性上调用addTagObject方法,而你应该在具有tags属性的对象上调用它。谢谢Keenle,我想不出来,所以我在这里发布了一个更全面的问题:谢谢,尽管后来发布了,你的答案更完整,我为此奖励你:)。这对我来说不起作用。在对to-many关系的父级调用remove函数后,尝试保存失败,因为子级仍然存在,但其与父级的所需关系为零。您是否检查了此操作是否有效?如果你在修改了员工设置后保存了模型,那么修改是否会被保存呢?我实际上在同一时刻使用了这种方法,它正在工作。很有趣!我不知道这是可能的。苹果真的应该澄清核心数据/Swift的使用情况,我认为……在一些常见的情况下,设置应该是可选的吗?还是最好在您的示例中定义它?这非常有帮助,谢谢。我发现很多核心数据信息都是以Objective-C约定表达的,因此,我们非常欣赏快速具体的解释。
@NSManaged var employees: Set<Employee>