How does one add an object to a relationship property in an NSManagedObject
subclass in Swift?
In Objective-C, when you generate an NSManagedObject
subclass in Xcode from the data model, there's an automatically generated class extension which contains declarations like:
@interface MyManagedObject (CoreDataGeneratedAccessors)
- (void)addMySubObject: (MyRelationshipObject *)value;
- (void)addMySubObjects: (NSSet *)values;
@end
However Xcode currently lacks this class generation capability for Swift classes.
If I try and call equivalent methods directly on the Swift object:
myObject.addSubObject(subObject)
...I get a compiler error on the method call, because these generated accessors are not visible.
I've declared the relationship property as @NSManaged
, as described in the documentation.
Or do I have to revert to Objective-C objects for data models with relationships?
Yeah that's not going to work anymore, Swift cannot generate accessors at runtime in this way, it would break the type system.
What you have to do is use the key paths:
Expanding on the solution above one to many relationships are NSMutableSet so this allows you to directly add or remove the Person NSManagedObject to the Roles in this case a Person has one Role and Roles have many Person(s)
I have tested this solution under Xcode Beta-3 and this works!
This code takes out the Department to simplify showing the one to one and one to many code required to access Roles from a Person and Persons from a Role.
Core Data in Objective C automatically creates setter methods (1):
As things currently stand with Swift in Xcode6-Beta2, you'd have to implement those accessors yourself. For example if you have an unordered to-many relationship, from
Way
toNode
, you'd implementaddNodesObject
like this:Key here is that you'd have to use
mutableSetValueForKey
/mutableOrderedSetValueForKey
/mutableArrayValueForKey
. On these sets / arrays, you can call addObject and they'll be stored on the next flush.As of Xcode 7 and Swift 2.0 (see release note #17583057), you are able to just add the following definitions to the generated extension file:
This works because
Adding this definition will allow you to add items to your collections. Not sure why these aren't just generated automatically...
As of Xcode 8 and Swift 3.0, Xcode now generates accessors for relationships. For example, I have an NSManagedObject class Store, that has a one to many relationship with Items; I've called that relationship SellsItems. The generated class for Store now has the following extension to add and remove from SellsItems. Adding or removing items to the relationship is as simple as calling these functions.
You can just use a typed
Set
instead which is far easier. Following the example provided by @Nycen and @lehn0058 in the previous answer, you can just write:And then use the
insert
andremove
methods of theSet
.