【问题标题】:Cocoa Touch Framework & CoreDataCocoa Touch 框架和 CoreData
【发布时间】:2017-06-01 14:16:24
【问题描述】:

我正在尝试在我的 Cocoa Touch 框架中使用 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!)

【问题讨论】:

  • 这似乎比它应该更难修复。 NSPersistentContainer 似乎无法在主包中找到模型,可能是因为您正在构建一个框架。您可以通过自己查找和指定模型来克服这个障碍,然后使用 NSPersistentContainer 的 name: managedObjectModel: 初始化程序,但随后您遇到了不同的问题...
  • 哈,这是很好的线索@jrturton!当然,这不是主要的 Bundle。我修复了它:let modelURL = Bundle(for: type(of: self)).url(forResource: "someDataModel", withExtension: "momd")! let managedObjectModel = NSManagedObjectModel(contentsOf: modelURL) let container = NSPersistentContainer(name: "someDataModel", managedObjectModel: managedObjectModel!) 谢谢!
  • 然后我收到无效的实体描述警告,我意识到我需要回去工作了,抱歉...

标签: ios swift core-data cocoa-touch


【解决方案1】:

TLDR;

Apple 建议您在框架中子类化 NSPersistentContainer。如果这样做,则将搜索定义子类的框架。

所以你可以简单地:

final class PersistentContainer: NSPersistentContainer { }

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

说明

name 初始化器只搜索主包。

要在不同的框架中查找托管对象模型,您可以按照 cmets 中的建议获取模型 URL。

但是,作为替代方案,您也可以在框架中子类化 NSPersistentContainer,然后 name 初始化程序将起作用。

这是 WWDC Core Data Best Practices 视频的摘录:

...假设我们想将模型层分解为自己的 框架。

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

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

这是因为它默认只检查主包。

为什么要停在那里?

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

我们如何解决这个问题?

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

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

我们需要做的就是创建一个子类。

它甚至不需要任何东西。

然后,通过容器设置的任何代码想要使用我们的 模型可以只采用该子类,而持久化容器将 而是为我们的模型签入我们的框架包。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-21
    • 2015-08-26
    • 1970-01-01
    • 1970-01-01
    • 2014-12-14
    • 2015-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多