Cocoa Touch Framework & CoreData



我正在尝试在我的Cocoa Touch Framework中使用CoreData。我创建了一个简单的项目作为示例:https://github.com/JakubMazur/SO41698466

基本上我是分步骤来做的:

  1. 创建一个带有单元测试的框架
  2. CoreData添加到项目someDataModel
  3. 用一些伪实体填充CoreData,并将模块更改为Current Product Module
  4. 然后我创建了SomeClass,它基本上被称为:

public class func entityCreation() {
Entity(context: CoreDataClass().persistentContainer.viewContext)
}

因此,有了这个来自CoreData的lazy自动生成的代码,就应该创建模型了。

  1. 在测试中,我写道:

func testExample() {
SomeClass.entityCreation()
}
  1. 并启动测试
  2. CoreDataClass中,我在以下行中放置了一个断点:let container = NSPersistentContainer(name: "someDataModel"),然后我在控制台中看到:

[error]错误:无法加载名为someDataModel的模型CoreData:错误:无法加载名为someDataModel 的模型

所以我有两个问题:

  1. 是否可以在框架中包含核心数据
  2. 如果1是真的,也许我应该使用不同的NSPersistentContainer名称?有一种方法可以检查我应该在那里放什么

在此处下载项目:https://github.com/JakubMazur/SO41698466

找到解决方案并在下面添加

let modelURL = Bundle(for: type(of: self)).url(forResource: "someDataModel", withExtension: "momd")! 
let managedObjectModel = NSManagedObjectModel(contentsOf: modelURL) 
let container = NSPersistentContainer(name: "someDataModel", managedObjectModel: managedObjectModel!)

TLDR

Apple建议您在框架中对NSPersistentContainer进行子类化。如果你这样做,那么将搜索子类定义的框架。

所以你可以简单地:

final class PersistentContainer: NSPersistentContainer { }

然后在您的框架中使用PersistentContainer而不是NSPersistentContainer

解释

name初始值设定项仅搜索主bundle。

要在不同的框架中查找托管对象模型,您可以获得注释中建议的模型URL。

然而,作为一种替代方案,您也可以在您的框架中对NSPersistentContainer进行子类化,然后name初始值设定项就可以工作了。

以下是WWDCCore Data Best Practices视频的摘录:

。。。假设我们想将模型层因素化为自己的模型层框架

我们可以通过在Xcode中创建一个新的框架目标并移动我们的代码。

这一切都非常容易,但当我们将模型移动到新目标时,在构建的产品中,目标从应用程序移动到新的框架,这是应该发生的事情,但现在NSPersistentContainer不知道在哪里可以找到我们的模型了。

这是因为默认情况下它只检查主捆绑包。

为什么停在那里?

好吧,搜索应用程序的所有捆绑包可能会变得非常慢复杂的应用程序,这不是你每次都想支付的成本旋转堆栈。

我们该如何解决这个问题?

好吧,我们可以从框架捆绑包中恢复模型我们自己,并使用容器的其他初始化程序之一,如采用显式托管对象模型,但NSPersistentContainer实际上有一种方法可以让你改变它搜索的捆绑包。

看,NSPersistentContainer知道它何时被子类化,并且将在查找模型时,使用子类的类型作为提示。

为了利用这一点,我们所需要做的就是创建一个子类。

它甚至不需要任何东西。

然后,通过容器设置的任何想要使用模型可以采用该子类,持久容器将请查看我们的模型的框架捆绑包。

https://asciiwwdc.com/2018/sessions/224

最新更新