I'm trying to migrate a specific part of one of my apps into a framework so that I can use it in my app itself and in one of those fancy new iOS 8 widgets. This part is the one that handles all my data in Core Data. It's pretty straight forward to move everything over and to access it. I'm just having trouble accessing my momd
file in there.
When creating the NSManagedObjectModel
I still try to load the momd
as illustrated in Apple's code templates:
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyApp" withExtension:@"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
Unfortunately, modelURL
stays nil
and thus MyApp
crashes when accessing the Core Data stack with this error:
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'
So, what's the right way to do this when working inside a framework with Core Data?
Core Data is designed to work in a multithreaded environment. However, not every object under the Core Data framework is thread safe. To use Core Data in a multithreaded environment, ensure that: Managed object contexts are bound to the thread (queue) that they are associated with upon initialization.
Most apps need just a single managed object context. The default configuration in most Core Data apps is a single managed object context associated with the main queue. Multiple managed object contexts make your apps harder to debug; it's not something you'd use in every app, in every situation.
A managed object context represents a single object space, or scratch pad, in a Core Data application. A managed object context is an instance of NSManagedObjectContext . Its primary responsibility is to manage a collection of managed objects.
I'm a bit late for flohei's issue, but hopefully this helps anybody else who wanders by. It is possible to get this to work without having to perform script-fu to copy resources around!
By default Apple's Core Data template gives you something like this:
lazy var managedObjectModel: NSManagedObjectModel = { let modelURL = NSBundle.mainBundle().URLForResource("MyCoreDataModel", withExtension: "momd")! return NSManagedObjectModel(contentsOfURL: modelURL)! }()
That would load your Core Data resources out of the main bundle. The key thing here is: if the Core Data model is loaded in a framework, the .momd file is in that framework's bundle. So instead we just do this:
lazy var managedObjectModel: NSManagedObjectModel = { let frameworkBundleIdentifier = "com.myorg.myframework" let customKitBundle = NSBundle(identifier: frameworkBundleIdentifier)! let modelURL = customKitBundle.URLForResource("MyCoreDataModel", withExtension: "momd")! return NSManagedObjectModel(contentsOfURL: modelURL)! }()
That should get you up and running.
Credit: https://www.andrewcbancroft.com/2015/08/25/sharing-a-core-data-model-with-a-swift-framework/
You need to drag the xcdatamodeld file and drop it in the Build Phases | Compile Sources for the targets that use the framework. Then when the target runs its [NSBundle mainBundle] will contain the model (momd file).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With