I'm trying to use CoreData
inside my Cocoa Touch Framework. I create a simple project as an example:
https://github.com/JakubMazur/SO41698466
Basically I do it in steps:
CoreData
to project someDataModel
CoreData
with some dummy Entity and change module to Current Product Module
SomeClass
to start with and it's basically called
:.
public class func entityCreation() {
Entity(context: CoreDataClass().persistentContainer.viewContext)
}
So with this lazy
autogenerated code from CoreData this should create model.
.
func testExample() {
SomeClass.entityCreation()
}
CoreDataClass
I put a breakpoint below line:
let container = NSPersistentContainer(name: "someDataModel")
and then I see in console:[error] error: Failed to load model named someDataModel CoreData: error: Failed to load model named someDataModel
So I have a 2 questions:
NSPersistentContainer
name? There is a way to check what should I put there?Download a project here: https://github.com/JakubMazur/SO41698466
Solution Found And Added below
let modelURL = Bundle(for: type(of: self)).url(forResource: "someDataModel", withExtension: "momd")!
let managedObjectModel = NSManagedObjectModel(contentsOf: modelURL)
let container = NSPersistentContainer(name: "someDataModel", managedObjectModel: managedObjectModel!)
Apple recommends that you subclass NSPersistentContainer
in your framework. If you do this then the framework which the subclass is defined in will be searched.
So you can simply:
final class PersistentContainer: NSPersistentContainer { }
Then use PersistentContainer
rather than NSPersistentContainer
in your framework.
The name
initializer only searches through the main bundle.
To find the managed object model in a different framework you can get the model URL as suggested in the comments.
However, as an alternative, you can also subclass the NSPersistentContainer
in your framework, then the name
initializer will work.
Here is an excerpt from the WWDC Core Data Best Practices
video:
... let's say we want to factor our model layer into its own framework.
We can do that by creating a new framework target in Xcode and moving our code into it.
It's all super easy, but when we move our model into the new target, in the built product, targets move from the app into the new framework, which is what's supposed to happen, but now NSPersistentContainer doesn't know where to find our model anymore.
This is because it only checks the main bundle by default.
Why stop there?
Well, searching all of the app's bundles could get really slow for a complicated app and it's not a cost you want to pay every time you spin up a stack.
How do we fix this?
Well, we could resuscitate the model out of the framework bundle ourselves and use one of the container's other initializers, like one that takes an explicit managed object model, but NSPersistentContainer actually has a way for you to change which bundle it searches.
See, NSPersistentContainer knows when it's been subclassed and will use the type of the subclass as a hint when it looks for the model.
All we need to do to take advantage of this is to create a subclass.
It doesn't even need to have anything in it.
Then, any code setting up through the container that wants to use our model can just adopt that subclass and the persistent container will check in our frameworks bundle for our model instead.
https://asciiwwdc.com/2018/sessions/224
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