如何在框架内使用Core Data的ManagedObjectModel?
我试图将我的一个应用程序的特定部分迁移到一个框架中,以便我可以在我的应用程序本身和其中一个新的iOS 8小部件中使用它。 这部分是处理所有我的数据在核心数据。 移动所有内容并访问它非常简单。 我只是无法在那里访问我的momd
文件。
当创buildNSManagedObjectModel
我仍然尝试加载苹果的代码模板中所示的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的框架内工作时,正确的方法是什么呢?
您需要将xcdatamodeld文件拖放到“构build阶段”中 为使用框架的目标编译源文件。 然后当目标运行时,它的[NSBundle mainBundle]将包含模型(momd文件)。
我对flohei的问题有点晚了,但希望这可以帮助其他人stream连忘返。 有可能得到这个工作,而不必执行脚本复制周围的资源!
默认情况下,苹果的核心数据模板给你这样的东西:
lazy var managedObjectModel: NSManagedObjectModel = { let modelURL = NSBundle.mainBundle().URLForResource("MyCuteCoreDataModel", withExtension: "momd")! return NSManagedObjectModel(contentsOfURL: modelURL)! }()
这将加载你的核心数据资源的主包。 这里最关键的是:如果Core Data模型被加载到一个框架中, .momd文件就在这个框架的bundle中 。 所以,我们只是这样做:
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/
@Ric桑托斯几乎在那里。 我想你只需要把它做成一个“妈妈”的延伸,而不是“妈妈”,那么它就会运行。
lazy var managedObjectModel: NSManagedObjectModel = { let modelURL = NSBundle(forClass: self.dynamicType.self).URLForResource(self.dataModelName, withExtension: "mom")! return NSManagedObjectModel(contentsOfURL: modelURL)! }()
我回答这个问题可能有点迟,但这是解决了我的问题:
在我的框架中,我还提供了一些资源,比如图像和其他东西。 把xcdatamodeld文件没有给任何东西,因为这个文件正在与项目构build,因此你得到一个妈妈文件夹在你的应用程序包(实际上是在我们的情况下丢失)..我已经创build了另一个目标,而不是框架,但应用程序,构build它,并从应用程序包复制到项目中的单独的包(与框架一起)。 做完这些之后,你只需要将你的资源URL从主包更改为新包:
// ... NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"separate_bundle" ofType:@"bundle"]; NSURL *modelURL = [[NSBundle bundleWithPath:bundlePath] URLForResource:@"your_model" withExtension:@"momd"]; // ...
为我工作得很好。 我唯一知道的是我还没有到的App Store Review。 所以,如果你find了更好的解决scheme,请分享。
编辑
find更好的解决 你可以自己build立模型。 核心数据编程指南 :
数据模型是一个部署资源。 除了模型中实体和属性的细节之外,您在Xcode中创build的模型还包含关于该图的信息 – 布局,元素的颜色等等。 后面的信息在运行时不需要。 使用模型编译器momc编译模型文件,以删除无关的信息,并尽可能高效地使运行时加载资源。 将一个xcdatamodeld“源”目录编译成一个momd部署目录,并将一个xcdatamodel“源”文件编译成一个mom部署文件。
momc位于/ Developer / usr / bin /中。 如果要在自己的构build脚本中使用它,则其用法是momc源目标,其中source是要编译的Core Data模型的path,destination是输出的path。
“/ Developer / usr / bin /”是“ /Applications/Xcode.app/Developer/usr/bin/ ”
您可以在目标scheme中添加一个脚本,并在每次构build之前自动编译这个脚本(或之后,不要以为这很重要)。 如果您在开发过程中更改模型,则会出现这种情况。
像这样的东西:
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"
模型资源不再可以通过mainBundle
访问,你需要使用bundleForClass:
like:
NSURL *modelURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"MyApp" withExtension:@"momd"]; _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
我假设你只需要数据模型。
如果是这样的话,我发现以下一直是跨数据模型文件从一个项目复制到另一个的最成功的方法…
- 删除驻留在目标项目中的任何当前的
.xcdatamodeld
文件副本。 -
closuresXcode。
使用Finder(或cmd行);
- select包含原始
.xcdatamodeld
文件的Xcode项目文件夹。 - 制作原始
.xcdatamodeld
文件的副本。 -
将原始
.xcdatamodeld
文件的副本移到您的目标项目。然后…
- 打开Xcode。
- 使用菜单命令“Add Files to> your project <”,find原始
.xcdatamodeld
文件的副本并将其添加到项目中。 - 使用Project Navigator重命名原始的
.xcdatamodeld
文件(如有必要)。 - “构build并运行”您的目标项目。
这有帮助吗?
如果你试图让你的框架中的核心数据这样做。
在YourFramework – 添加新的文件/核心数据/数据模型… – 创build所有对象….
创build将使用YourFramework的新项目时,请确保核心数据已打开
这将创buildAppDelegate内的所有锅炉板。
在testing项目 – 添加框架 – 添加框架作为embedded式框架 – 删除.xcdatamodeld文件 – 在AppDelegate:
把- (NSManagedObjectModel *)managedObjectModel
方法改成:
NSBundle * testBundle = [NSBundle bundleWithIdentifier:@"YourFramework bundle id "]; NSURL *modelURL = [testBundle URLForResource:@"Model" withExtension:@"momd"];
YourFramework bundle id
是YourFramework bundle id
Bundle Identifier(在General / Bundle Identifier中)
Model
是YourFramework中.xcdatamodeld文件的名称
这工作。
希望能帮助到你。