如何在框架内使用Core Data的ManagedObjectModel?

时间:2014-08-01 20:43:24

标签: ios core-data frameworks nsbundle nsmanagedobjectmodel

我尝试将我的某个应用程序的特定部分迁移到框架中,以便我可以在我的应用程序本身和其中一个新的iOS 8小部件中使用它。这部分是处理Core Data中所有数据的部分。它非常直接地将所有内容移动并访问它。我在访问momd文件时遇到问题。

创建NSManagedObjectModel时,我仍尝试按照Apple代码模板中的说明加载momd

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyApp" withExtension:@"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

不幸的是,modelURL在访问核心数据堆栈时因此错误而停留nil,因此MyApp崩溃:

2014-08-01 22:39:56.885 MyApp[81375:7417914] Cannot create an NSPersistentStoreCoordinator with a nil model
2014-08-01 22:39:56.903 MyApp[81375:7417914] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot create an NSPersistentStoreCoordinator with a nil model'

那么,在使用Core Data在框架内工作时,采用这种方法的正确方法是什么?

7 个答案:

答案 0 :(得分:21)

对于弗洛赫的问题,我有点迟了,但希望这可以帮助其他任何徘徊的人。有可能让这个工作无需执行脚本fu来复制资源!

默认情况下,Apple的核心数据模板会为您提供以下内容:

lazy var managedObjectModel: NSManagedObjectModel = {
  let modelURL = NSBundle.mainBundle().URLForResource("MyCuteCoreDataModel", withExtension: "momd")!
  return NSManagedObjectModel(contentsOfURL: modelURL)!
}()

这会将您的核心数据资源从主捆绑中加载出来。这里的关键是:如果Core Data模型是在框架中加载的,那么 .momd文件就在该框架的中。所以我们只是这样做:

lazy var managedObjectModel: NSManagedObjectModel = {
    let sexyFrameworkBundleIdentifier = "com.heybaby.xxx"
    let customKitBundle = NSBundle(identifier: sexyFrameworkBundleIdentifier)!
    let modelURL = customKitBundle.URLForResource("MyCuteCoreDataModel", withExtension: "momd")!
    return NSManagedObjectModel(contentsOfURL: modelURL)!
}()

这应该让你起步并运行。

信用:https://www.andrewcbancroft.com/2015/08/25/sharing-a-core-data-model-with-a-swift-framework/

答案 1 :(得分:13)

您需要拖动xcdatamodeld文件并将其放入Build Phases |中编译使用该框架的目标的源。然后当目标运行时,它的[NSBundle mainBundle]将包含模型(momd文件)。

答案 2 :(得分:6)

@Ric Santos几乎就在那里。我想你只需要把它变成一个妈妈"扩展而不是"妈妈"然后它会运行。

lazy var managedObjectModel: NSManagedObjectModel = {
    let modelURL = NSBundle(forClass: self.dynamicType.self).URLForResource(self.dataModelName, withExtension: "mom")!
    return NSManagedObjectModel(contentsOfURL: modelURL)!
}()

答案 3 :(得分:4)

我回答这个问题可能有点晚了,但是这解决了我的问题:

通过我的框架,我还可以提供包含图像和其他内容等资源的捆绑包。放置 xcdatamodeld 文件并没有提供任何内容,因为这个文件是使用项目构建的,因此您的应用包中会出现 momd 文件夹(实际上是在我们的案例中失踪了).. 我创建了另一个目标,而不是框架,但app,构建它并将momd从其app包复制到我在项目中的单独bundle(与框架一起使用的那个)。 执行此操作后,您只需将资源URL从主程序包更改为新的:

// ...
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"separate_bundle" ofType:@"bundle"];
NSURL *modelURL = [[NSBundle bundleWithPath:bundlePath] URLForResource:@"your_model" withExtension:@"momd"];
// ...

对我来说很好。我唯一知道的是App Store Review,我还没有达到。 因此,如果您找到了更好的解决方案,请分享。

修改

找到更好的解决方案。您可以自己构建模型。来自Core Data Programming Guide

  

数据模型是部署资源。除了细节之外   模型中的实体和属性,您在Xcode中创建的模型   包含有关图表的信息 - 其布局,元素的颜色,   等等。在运行时不需要后一个信息。该模型   使用模型编译器momc编译文件来删除   无关信息并将资源的运行时加载为   尽可能高效。编译了一个xcdatamodeld“source”目录   到一个妈妈部署目录,和一个xcdatamodel“源”文件是   编译成妈妈部署文件。

     

momc位于/ Developer / usr / bin /。如果你想在你的   自己的构建脚本,它的用法是momc源目的地,源码   是要编译的核心数据模型的路径,目标是   输出的路径。

" / Developer / usr / bin /"他们的意思是" /Applications/Xcode.app/Developer/usr/bin / "

您可以在目标方案中添加脚本,并在每次构建之前自动编译(或之后,不要认为它很重要)。如果您在开发期间更改模型,则会出现这种情况。

这样的事情:

mkdir -p "${BUILT_PRODUCTS_DIR}/your_model_name.momd"
momc "${SRCROOT}/your_model_path/your_model_name.xcdatamodeld" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/your_bundle_name.bundle/your_model_name.momd"

答案 4 :(得分:2)

无法再通过mainBundle访问模型资源,您需要使用bundleForClass:,如下所示:

NSURL *modelURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"MyApp" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

答案 5 :(得分:0)

我假设您只需要数据模型。

如果是这样,我发现以下内容始终是将数据模型文件从一个项目复制到另一个项目的最成功方法......

  1. 删除目标项目中.xcdatamodeld文件的所有当前副本。
  2. 关闭Xcode。

    使用Finder(或cmd行);

  3. 选择包含原始.xcdatamodeld文件的Xcode项目文件夹。
  4. 制作原始.xcdatamodeld文件的副本。
  5. 将原始.xcdatamodeld文件的副本移至目标项目。

    则...

  6. 打开Xcode。
  7. 使用菜单命令“将文件添加到>您的项目<”,找到并将原始.xcdatamodeld文件的副本添加到您的项目中。
  8. 使用Project Navigator重命名原始.xcdatamodeld文件(如有必要)。
  9. “构建并运行”您的目标项目。
  10. 这有帮助吗?

答案 6 :(得分:0)

如果您尝试在框架中拥有核心数据,请执行此操作。

在YourFramework中

  - 添加新文件/核心数据/数据模型......   - 创建所有对象....

创建将使用YourFramework的新项目时,请确保核心数据位于Use Core Data : On

这将在AppDelegate中创建所有锅炉板。

在测试项目中   - 添加框架   - 将Framework添加为嵌入式框架   - DELETE .xcdatamodeld文件   - 在AppDelegate中:

- (NSManagedObjectModel *)managedObjectModel方法更改为:

NSBundle * testBundle = [NSBundle bundleWithIdentifier:@"YourFramework bundle id "];

NSURL *modelURL = [testBundle URLForResource:@"Model" withExtension:@"momd"];

其中YourFramework bundle id是YourFramework的捆绑标识符(通用/捆绑标识符)

Model是YourFramework中.xcdatamodeld文件的名称

这很有效。

希望它有所帮助。