How to assign CoreData many-to-many relationship in Swift?
Solution 1
As of Xcode 7 and Swift 2.0, the release note 17583057 states:
The NSManaged attribute can be used with methods as well as properties, for access to Core Data’s automatically generated Key-Value-Coding-compliant to-many accessors.
@NSManaged var employees: NSSet
@NSManaged func addEmployeesObject(employee: Employee)
@NSManaged func removeEmployeesObject(employee: Employee)
@NSManaged func addEmployees(employees: NSSet)
@NSManaged func removeEmployees(employees: NSSet)
These can be declared in your NSManagedObject subclass. (17583057)
So you just have to declare the following methods and CoreData will take care of the rest:
@NSManaged func addDogBreedsObject(dogBreed: DogBreed)
@NSManaged func removeDogBreedsObject(dogBreed: DogBreed)
@NSManaged func addDogBreeds(dogBreeds: NSSet)
@NSManaged func removeDogBreeds(dogBreeds: NSSet)
Solution 2
Swift cannot generate dynamic runtime accessors due to strict type system. You can create an extension to Disease
class and add missed methods manually, here is the code:
extension Disease {
func addDogBreedObject(value:DogBreed) {
var items = self.mutableSetValueForKey("dogBreed");
items.addObject(value)
}
func removeDogBreedObject(value:DogBreed) {
var items = self.mutableSetValueForKey("dogBreed");
items.removeObject(value)
}
}
Remarks:
I suggest you to create separate file for extension Disease+CoreData.swift
, This should help to keep your code from overrides when you re-generate the CoreData
model.
It is sufficient to create relationship in one of managed objects, second one will be updated with back reference. (Same as was with Objective-C)
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.Disease
Answer inspired by: Setting an NSManagedObject relationship in Swift
Solution 3
If you are looking for a simple approach just use this.
import CoreData
extension NSManagedObject {
func addObject(value: NSManagedObject, forKey: String) {
var items = self.mutableSetValueForKey(forKey);
items.addObject(value)
}
}
The implementation:
department.addObject(section, forKey: "employees")
Instead of writing the same method on every NSManageObject class that needs it.
Solution 4
Actually you can just write:
@NSManaged var dogBreed: Set<DogBreed>
And use the insert
and remove
methods of the Set
directly.
Solution 5
As an extension to @Naz. And in combination with @Ash's comment. I've found the only working solution for xCode 6.3.1
import CoreData
extension NSManagedObject {
func addObject(value: NSManagedObject, forKey: String) {
self.willChangeValueForKey(forKey, withSetMutation: NSKeyValueSetMutationKind.UnionSetMutation, usingObjects: NSSet(object: value) as Set<NSObject>)
var items = self.mutableSetValueForKey(forKey);
items.addObject(value)
self.didChangeValueForKey(forKey, withSetMutation: NSKeyValueSetMutationKind.UnionSetMutation, usingObjects: NSSet(object: value) as Set<NSObject>)
}
}
You have to call the willChange and didChange handlers in order to correctly add an object to a to-many relationship in Swift.
myManagedObject.addObject(value, forKey: "yourKey")
Related videos on Youtube
tadasz
Updated on September 15, 2022Comments
-
tadasz over 1 year
I have a NSManagedObject class
class Disease: NSManagedObject { @NSManaged var diseaseId: String @NSManaged var diseaseName: String @NSManaged var dogBreed: NSSet }
How do I add a new relationship to dogBreed? If i change var type to NSMutableSet, the changes are not saved to database. Any ideas?
-
Ash about 9 yearsI found that this code would not work for my app without wrapping the setting process in the proper key value observation code, to whit self.willChangeValueForKey("key", withSetMutation:<set mutation type>, usingObjects:<objects changed>) and the corresponding didChangeValueForKey method. Without this all kinds of strange and apparently unrelated errors were reported.
-
Keenle about 9 yearsGood point. I'll test your suggestion and add to the answer when back to my dev desktop.
-
Ali Beadle about 9 yearsAh ha - I like this solution. Neat.
-
Ben Guild almost 8 yearsI can't believe this is still a bug. Maybe in a week or so they'll fix it at WWDC.