Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
628 views
in Technique[技术] by (71.8m points)

core data - How to define CoreData relationship in Swift?

In CoreData, I have defined an unordered to-many relationship from Node to Tag. I've created an Swift entity like this:

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

Now I want to add a Tag to an instance of Node, like this:

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

However, this fails with the following error:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for to-many relationship: property = "tags"; desired type = NSSet; given type = _TtCSs22ContiguousArrayStorage000000000B3440D4; value = ( "<_TtC8MotorNav3Tag: 0xb3437b0> (entity: Tag; id: 0xb343800 ; data: {...})" ).'

What is the correct type for to-many relationships?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

To be able to work with one-to-many relationship in Swift you need to define property as:

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

If you try to use NSMutableSet changes will not be saved in CoreData. And of course it is recommended to define reverse link in Node:

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

But still Swift cannot generate dynamic accessors in runtime, so we need to define them manually. It is very convenient to define them in class extension and put in Entity+CoreData.swift file. Bellow is content of Node+CoreData.swift file:

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)
    }
}

Usage:

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

Important: To make it all work you should verify that class names of entities in you CoreData model includes your module name. E.g. MyProjectName.Node


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...