【问题标题】:How to assign CoreData many-to-many relationship in Swift?如何在 Swift 中分配 CoreData 多对多关系?
【发布时间】:2014-09-05 12:46:16
【问题描述】:

我有一个 NSManagedObject 类

class Disease: NSManagedObject {
    @NSManaged var diseaseId: String
    @NSManaged var diseaseName: String
    @NSManaged var dogBreed: NSSet
}

如何向 dogBreed 添加新关系?如果我将 var 类型更改为 NSMutableSet,则更改不会保存到数据库中。有什么想法吗?

【问题讨论】:

标签: ios cocoa-touch core-data swift


【解决方案1】:

从 Xcode 7 和 Swift 2.0 开始,release note 17583057 声明:

NSManaged 属性可以与方法一起使用,也可以用于 属性,用于访问 Core Data 自动生成的 与许多访问者的键值编码兼容。

@NSManaged var employees: NSSet

@NSManaged func addEmployeesObject(employee: Employee)
@NSManaged func removeEmployeesObject(employee: Employee)
@NSManaged func addEmployees(employees: NSSet)
@NSManaged func removeEmployees(employees: NSSet)

这些可以在你的 NSManagedObject 子类中声明。 (17583057)

因此,您只需声明以下方法,CoreData 将负责其余的工作:

@NSManaged func addDogBreedsObject(dogBreed: DogBreed)
@NSManaged func removeDogBreedsObject(dogBreed: DogBreed)
@NSManaged func addDogBreeds(dogBreeds: NSSet)
@NSManaged func removeDogBreeds(dogBreeds: NSSet)

【讨论】:

  • 谢谢! + 100
  • 这可能很奇怪而且迟到了,但是 Swift 怎么知道如何处理剩下的事情呢?您没有指定函数必须添加到哪个集合?
  • @Emptyless 这与 Swift 关系不大。这些方法是由 CoreData 生成的,实际上是 NSManaged 类负责处理它。上面的答案只是解释了使用 Swift 的正确方法。这与在 UIViewControllers 中声明 IBOutlets 非常相似,并且您询问 Swift 如何知道如何将其链接到 Storyboard(它也不是 Swift,它是 UIKit)
  • 你说它们是生成的,但也许我错过了什么?我添加了从俱乐部到会员的两种关系,反之亦然。我已经将它们设置为许多关系,并让它们指向它们自己。仍然当我生成 NSManagedSubclasses 时,其中没有任何方法。只有 NSSet,因此导致我的问题是如何将这些方法指向 NSSet。提前致谢!
  • @Emptyless 一方面有 CoreData 生成的底层 Key-Value 方法,另一方面还有依赖这些方法的 Swift 方法。当您生成 NSManagedSubclasses 时,XCode 会生成一些(但不是全部)上述 Swift 方法以节省您一些时间。即使底层 KV 方法已经存在,您也必须手动编写它不会为您生成的那些。
【解决方案2】:

由于严格的类型系统,Swift 无法生成动态运行时访问器。您可以为Disease 类创建扩展并手动添加错过的方法,代码如下:

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

备注:

我建议您为扩展 Disease+CoreData.swift 创建单独的文件,这应该有助于在您重新生成 CoreData 模型时防止您的代码被覆盖。

在其中一个托管对象中创建关系就足够了,第二个将使用反向引用进行更新。 (与 Objective-C 相同)

重要提示:为了使这一切正常工作,您应该验证 CoreData 模型中实体的类名称是否包含您的模块名称。例如。 MyProjectName.Disease

答案灵感来自:Setting an NSManagedObject relationship in Swift

【讨论】:

  • 我发现如果不将设置过程包装在正确的键值观察代码中,此代码将不适用于我的应用程序,即 self.willChangeValueForKey("key", withSetMutation:, usingObjects:) 和相应的 didChangeValueForKey 方法。如果没有这个,就会报告各种奇怪且明显无关的错误。
  • 好点。当我回到我的开发桌面时,我会测试你的建议并添加到答案中。
【解决方案3】:

如果您正在寻找一种简单的方法,请使用它。

import CoreData
extension NSManagedObject {
    func addObject(value: NSManagedObject, forKey: String) {
        var items = self.mutableSetValueForKey(forKey);
        items.addObject(value)
    }
}

实现:

department.addObject(section, forKey: "employees")

而不是在每个需要它的 NSManageObject 类上编写相同的方法。

【讨论】:

  • 啊哈 - 我喜欢这个解决方案。整洁。
【解决方案4】:

其实你可以写:

@NSManaged var dogBreed: Set<DogBreed>

并直接使用Setinsertremove方法。

【讨论】:

    【解决方案5】:

    作为@Naz 的扩展。并结合@Ash 的评论。我找到了 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>)
        }
    }
    

    您必须调用 willChange 和 didChange 处理程序才能正确地将对象添加到 Swift 中的一对多关系中。

    myManagedObject.addObject(value, forKey: "yourKey")
    

    【讨论】:

      【解决方案6】:

      @Nycen 为 Xcode 7 提供了现在自动实现的方法的最佳解决方案,但是请注意,NSOrderedSet 问题几乎令人难以置信地仍然存在(请参阅this question),因此如果使用NSOrderedSet 来表示您的关系而不是NSSet 您仍然需要使用解决方法。

      (我会发表评论而不是发布新答案,但是我缺乏积分)

      【讨论】:

      • 我不敢相信这仍然是一个错误。也许在一周左右的时间里,他们会在 WWDC 上修复它。
      【解决方案7】:

      如果您需要使用NSOrderedSet 而不是NSSet,我一直在使用以下代码,这样可以更轻松地使用NSMutableOrderedSet 添加、插入和删除对象的方法。

      @NSManaged private var myOrderedSet: NSOrderedSet
      
      var myMutableOrderedSet: NSMutableOrderedSet {
          return self.mutableOrderedSetValueForKey("myOrderedSet")
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多