ios 在 Swift 中设置 NSManagedObject 关系

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24146524/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 00:47:07  来源:igfitidea点击:

Setting an NSManagedObject relationship in Swift

iosmacoscore-dataswiftnsmanagedobject

提问by Andrew Ebling

How does one add an object to a relationship property in an NSManagedObjectsubclass in Swift?

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

In Objective-C, when you generate an NSManagedObjectsubclass in Xcode from the data model, there's an automatically generated class extension which contains declarations like:

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

@interface MyManagedObject (CoreDataGeneratedAccessors)

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

@end

However Xcode currently lacks this class generation capability for Swift classes.

然而,Xcode 目前缺乏 Swift 类的此类生成功能。

If I try and call equivalent methods directly on the Swift object:

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

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.

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

Or do I have to revert to Objective-C objects for data models with relationships?

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

采纳答案by iluvcapra

Yeah that's not going to work anymore, Swift cannot generate accessors at runtime in this way, it would break the type system.

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

What you have to do is use the key paths:

您需要做的是使用关键路径:

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

回答by lehn0058

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:

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

This works because

这有效,因为

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 属性可以与方法和属性一起使用,用于访问 Core Data 自动生成的符合 Key-Value-Coding 的 to-many 访问器。

Adding this definition will allow you to add items to your collections. Not sure why these aren't just generated automatically...

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

回答by Bouke

Core Data in Objective C automatically creates setter methods (1):

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

By default, Core Data dynamically creates efficient public and primitive get and set accessor methods for modeled properties (attributes and relationships) of managed object classes. This includes the key-value coding mutable proxy methods such as addObject: and removes:, as detailed in the documentation for mutableSetValueForKey:—managed objects are effectively mutable proxies for all their to-many relationships.

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

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 Wayto Node, you'd implement addNodesObjectlike this:

就目前 Xcode6-Beta2 中的 Swift 而言,您必须自己实现这些访问器。例如,如果您有一个无序的对多关系, from Wayto Node,您可以addNodesObject像这样实现:

class Way : NSManagedObject {
    @NSManaged var nodes : NSSet

    func addNodesObject(value: Node) {
        self.mutableSetValueForKey("nodes").addObject(value)
    }
}

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.

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

回答by FranMowinckel

You can just use a typed Setinstead which is far easier. Following the example provided by @Nycen and @lehn0058 in the previous answer, you can just write:

您可以只使用 typedSet来代替,这要容易得多。按照上一个答案中@Nycen 和@lehn0058 提供的示例,您可以只写:

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

And then use the insertand removemethods of the Set.

然后使用 的insertremove方法Set

回答by BadDogApps

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)

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

I have tested this solution under Xcode Beta-3 and this works!

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

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.

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

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

}

回答by Mario Hendricks

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.

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

回答by Peter

As you only need to set one side of a relationship for both to be set nowadays, it's particularly simple if you have a 1<->many relationship, e.g. a Department object has multiple Person objects, then you can just use:

由于您现在只需要设置关系的一侧即可设置两者,如果您有 1<->many 关系,则特别简单,例如 Department 对象有多个 Person 对象,那么您可以使用:

aPerson.department = aDepartment

If you check you'll find that aDepartment.people (assuming that is the reciprocal relationship you've set up) will now contain the 'aPerson' Person object.

如果您检查一下,您会发现 aDepartment.people(假设这是您设置的互惠关系)现在将包含“aPerson”Person 对象。

If the relationship is many<->many then one of the more complex solutions above appears necessary.

如果关系是多<->多,那么上述更复杂的解决方案之一似乎是必要的。

回答by Erik

Let's say you have the following entities:

假设您有以下实体:

  • Person
  • Role
  • Department
  • 角色
  • 部门

In your Personentity, they have a to-many relationship with Roleand to-one with Department. Your managed object might look something like this:

在您的Person实体中,它们与Role和一对多关系Department。您的托管对象可能如下所示:

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

Relationships with inverses (all should have them) only require one side to be set for the link to be established.

与逆的关系(都应该有)只需要设置一侧即可建立链接。

For example, if you set a Person's departmentproperty to a Departmentobject, the inverse Department.peopleproperty would now also have this Personobject contained inside.

例如,如果您将 aPersondepartment属性设置为一个Department对象,则 inverseDepartment.people属性现在也将包含该Person对象。