在Swift中设置NSManagedObject关系

And*_*ing 34 macos core-data nsmanagedobject ios swift

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

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

@interface MyManagedObject (CoreDataGeneratedAccessors)

     - (void)addMySubObject: (MyRelationshipObject *)value;
     - (void)addMySubObjects: (NSSet *)values;

@end
Run Code Online (Sandbox Code Playgroud)

然而,Xcode目前缺乏Swift类的这一类生成功能.

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

myObject.addSubObject(subObject)
Run Code Online (Sandbox Code Playgroud)

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

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

或者我是否必须为具有关系的数据模型恢复Objective-C对象?

leh*_*058 46

从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>)
}
Run Code Online (Sandbox Code Playgroud)

这是因为

NSManaged属性可以与方法和属性一起使用,以访问Core Data自动生成的符合键值编码的多个访问器.

添加此定义将允许您向集合中添加项目.不确定为什么这些不仅仅是自动生成的......

  • 确保方法名称与密钥完全匹配!! 如果我有一组猴子,那么该方法将是@NSManaged func addMonkeysObject(value:Monkey) - 如果你遗漏了尾随s,它将崩溃. (5认同)
  • 这应该是可接受的答案,因为它依赖于CoreData访问器. (2认同)

ilu*_*pra 32

是的,这不再适用了,Swift无法以这种方式在运行时生成访问器,它会破坏类型系统.

你要做的是使用关键路径:

var manyRelation = myObject.valueForKeyPath("subObjects") as NSMutableSet
manyRelation.addObject(subObject)
/* (Not tested) */
Run Code Online (Sandbox Code Playgroud)

  • 实际上你可以使用`myObject.mutableSetValueForKey()`然后你不需要强制转换. (6认同)
  • 该关系最有可能以"NSMutableSet"而不是"NSMutableArray"的形式返回.只有一个有序的关系将作为`NSMutableArray`返回. (3认同)

Bou*_*uke 19

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

默认情况下,Core Data为托管对象类的建模属性(属性和关系)动态创建有效的公共和原始get和set访问器方法.这包括键值编码可变代理方法,如addObject:和removed:,详见mutableSetValueForKey的文档: - 托管对象是所有多对多关系的有效可变代理.

正如目前Swift在Xcode6-Beta2中所做的那样,你必须自己实现这些访问器.例如,如果你有一个无序的一对多的关系,从WayNode,你会实现addNodesObject这样的:

class Way : NSManagedObject {
    @NSManaged var nodes : NSSet

    func addNodesObject(value: Node) {
        self.mutableSetValueForKey("nodes").addObject(value)
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 在XCode 6 GM中引起无限递归,类似BadDogApps的答案似乎有效. (3认同)
  • 有没有人在最新的Xcode中使用它?在向mutableSetValueForKey添加对象时,我也会得到无限循环 (2认同)

小智 6

扩展一对多关系上面的解决方案是NSMutableSet所以这允许您直接向角色添加或删除Person NSManagedObject,在这种情况下,Person有一个角色,角色有很多Person

我已经在Xcode Beta-3下测试了这个解决方案,这个有效!

此代码取出部门以简化显示从角色的人员和角色访问角色所需的一对一和一对多代码.

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

}
Run Code Online (Sandbox Code Playgroud)

  • 避免使用复数"角色",而不是"角色"甚至是原来的"部门",会更好. (2认同)
  • 直到今天我都使用这种方法,遇到一个问题,即在保存和加载上下文后,集合不包含添加到其中的对象。使用上面答案中提到的“mutableSetValueForKey”解决了这个问题。 (2认同)

Fra*_*kel 6

您可以使用类型Set而不是更容易.按照@Nycen和@ lehn0058在上一个答案中提供的示例,您可以写:

extension PersonModel {
    @NSManaged var parents: Set<ParentModel>?
}
Run Code Online (Sandbox Code Playgroud)

然后使用insert和的remove方法Set.


小智 5

从Xcode 8和Swift 3.0开始,Xcode现在为关系生成访问器.例如,我有一个NSManagedObject类Store,它与Items有一对多的关系; 我把这种关系称为SellsItems.现在,Store的生成类具有以下扩展名,可以从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)
}
Run Code Online (Sandbox Code Playgroud)