Adding Core Data in a Swift Package
Let’s add a Core Data manager and model to a Swift package

When creating an app, its architecture should be modular, so that dependencies can be recognized and managed clearly and as simple as possible.
Swift packages are a convenient way to separate concerns, for instance, by extracting the persistent store to a package. However, when talking of Core Data stores, this is not as trivial as it seems.
This article describes a method how this can succeed, avoiding errors like “model not found”.
Basic Requirements
There shall be a package “Persistence” that holds a Core Data manager, as well as the Core Data model.
Other packages shall be able to use that package, in order to access the managed objects, as well as the manager itself.
Additionally, it shall be possible to set up different managers:
- A manager for a temporary store, for usage with tests or other purposes.
- A manager for a local store, if no iCloud is active.
- A manager for a cloud store, if iCloud is available.
Finally, there shall be not a singleton implementation.
The Implementation
After creating a new package “Persistence” in Xcode, we need a package configuration:
Next, we add a protocol where the manager variants can conform to:
The configuration helps us to provide the basic settings:
Subclassing the Container
Actually, we just have to use a NSPersistentContainer
now to set up the store. However, according to Apple, this class should be subclassed in order to easier control where the store shall be stored.
Therefore, we’re creating two subclasses (for local or temporary storage, and for cloud storage). In these subclasses we override the defaultDirectoryURL
method in order to put the stores in appropriate places:
Conforming to the Protocol
Now we create our first implementation of the protocol we defined:
Here, we set up a temporary store for a given configuration that provides the name of the model. There is an important piece that is hidden in the ?TemporaryPersistenceManager.model(for:)
function:
Two things are relevant here:
- First, the URL must be retrieved from the package, therefore
Bundle.module.url(forResource:withExtension:)
must be used. - Second, although usually the extension
momd
is used, it is necessary to use justmom
here. Otherwise, the model will not be found correctly.
You may now want to implement a LocalPersistenceManager
and a CloudPersistenceManager
in a similar way, I will not point out this here.
Using our Managers
Now, after adding the package to our app, we can use the manager there. In our example here, we’re using Resolver for registering our MetaDataService<>
services that use the managers:
The MetaDataService<>
services are defined in a package Meta
on their own. That package just references the Persistence
package:
Conclusion
I struggled a lot with errors that occurred at runtime (not at build time) because the model was not found. The solution presented here is now building and running properly.
However, there is still one thing left: although the Xcode console shows an error when the store is set up the very first time (something like “cannot create file”), the store is set up correctly. If you have any idea why, please leave a comment.
Thanks for reading this article, I hope it can save you some troubleshooting time in similar situations.