在Swift中设置一个NSManagedObject关系

在Swift的NSManagedObject子类中,如何将对象添加到关系属性中?

在Objective-C中,当从数据模型生成Xcode中的NSManagedObject子类时,会自动生成类扩展,其中包含如下声明:

 @interface MyManagedObject (CoreDataGeneratedAccessors) - (void)addMySubObject: (MyRelationshipObject *)value; - (void)addMySubObjects: (NSSet *)values; @end 

但是,Xcode目前缺lessSwift类的这个类生成能力。

如果我尝试直接在Swift对象上调用等价的方法:

 myObject.addSubObject(subObject) 

…我在方法调用中遇到编译器错误,因为这些生成的访问器不可见。

我已经将关系属性声明为@NSManaged ,如文档中所述。

还是必须恢复到具有关系的数据模型的Objective-C对象?

是的,这是行不通的,Swift不能在运行时以这种方式生成访问器,它会打破types系统。

你必须做的是使用关键path:

 var manyRelation = myObject.valueForKeyPath("subObjects") as NSMutableSet manyRelation.addObject(subObject) /* (Not tested) */ 

从Xcode 7和Swift 2.0开始(请参阅发行说明#17583057 ),只需将以下定义添加到生成的扩展文件即可:

 extension PersonModel { // This is what got generated by core data @NSManaged var name: String? @NSManaged var hairColor: NSNumber? @NSManaged var parents: NSSet? // This is what I manually added @NSManaged func addParentsObject(value:ParentModel) @NSManaged func removeParentsObject(value:ParentModel) @NSManaged func addParents(value:Set<ParentModel>) @NSManaged func removeParents(value:Set<ParentModel>) } 

这是因为

NSManaged属性可以与方法和属性一起使用,以访问Core Data自动生成的Key-Value-Coding兼容的多对多访问器。

添加此定义将允许您将项目添加到您的集合。 不知道为什么这些不是自动生成的…

Objective C中的核心数据自动创buildsetter方法( 1 ):

默认情况下,Core Data为受pipe对象类的build模属性(属性和关系)dynamic创build高效的公共和原始get和set访问器方法。 这包括键值编码可变代理方法,如addObject:和removed :,如在mutableSetValueForKey的文档中详细描述的: – pipe理对象对于所有的一对多关系都是有效的可变代理。

就像Xcode6-Beta2中的Swift一样,你必须自己实现这些访问器。 例如,如果你有一个无序的一对多的关系,从WayNode ,你addNodesObject像这样实现addNodesObject

 class Way : NSManagedObject { @NSManaged var nodes : NSSet func addNodesObject(value: Node) { self.mutableSetValueForKey("nodes").addObject(value) } } 

这里的关键是你必须使用mutableSetValueForKey / mutableOrderedSetValueForKey / mutableArrayValueForKey 。 在这些集合/数组上,你可以调用addObject,它们将被存储在下一次刷新。

在NSMutableSet之上扩展解决scheme是NSMutableSet,因此这允许您直接添加或删除Person NSManagedObject到angular色,在这种情况下,Person有一个angular色,angular色有很多Person(s)

我已经在Xcode Beta-3下testing了这个解决scheme,并且这个工作正常!

此代码取出部门以简化显示从angular色中访问人员和人员所需的“一对一”和“一对多”代码。

 import CoreData @objc(Person) class Person: NSManagedObject { @NSManaged var name: String //One to One relationship in your Model @NSManaged var roles: Roles } @objc(Roles) class Roles: NSManagedObject { @NSManaged var role: String //One to Many relationship in your Model @NSManaged var persons: NSMutableSet } extension Roles { func addPersonsObject(value: Person) { self.persons.addObject(value) } func removePersonsObject(value: Person) { self.persons.removeObject(value) } func addPersons(values: [Person]) { self.persons.addObjectsFromArray(values) } func removePersons(values: [Person]) { for person in values as [Person] { self.removePersonsObject(person) } } } 

你可以使用一个types的Set而不是更容易。 在上一个答案中@Nycen和@ lehn0058提供的示例之后,您可以只写:

 extension PersonModel { @NSManaged var parents: Set<ParentModel>? } 

然后使用Setinsertremove方法。

从Xcode 8和Swift 3.0开始,Xcode现在生成关系访问器。 例如,我有一个NSManagedObject类的商店,它与项目有一对多的关系; 我把这个关系叫做SellsItems。 现在,商店生成的类具有以下扩展来添加和从SellsItems中删除。 向关系中添加或删除项目与调用这些函数一样简单。

 // MARK: Generated accessors for sellsItems extension Store { @objc(addSellsItemsObject:) @NSManaged public func addToSellsItems(_ value: Item) @objc(removeSellsItemsObject:) @NSManaged public func removeFromSellsItems(_ value: Item) @objc(addSellsItems:) @NSManaged public func addToSellsItems(_ values: NSSet) @objc(removeSellsItems:) @NSManaged public func removeFromSellsItems(_ values: NSSet) } 

因为你现在只需要设置关系的一个方面,如果你有一个1 < – >多的关系,例如一个Department对象有多个Person对象,那么你就可以使用:

 aPerson.department = aDepartment 

如果你检查你会发现aDepartment.people(假设这是你build立的相互关系)现在将包含'aPerson'Person对象。

如果关系很多,那么上面的一个更复杂的解决scheme似乎是必要的。

假设您有以下实体:

  • angular色

在你的Person实体中,他们与Role有一个多对多的关系,并且与Department有一个关系。 您的托pipe对象可能如下所示:

 class Person : NSManagedObject { @NSManaged var roles : Array<Role> @NSManaged var department : Department } 

与反向的关系(都应该有它们)只需要为要build立的链接设置一个方面。

例如,如果将Persondepartment属性设置为Department对象,则Department.people的逆向属性现在也将包含此Person对象。