Core Data and Swift Package Manager
Swift Package Manager smoothly integrates with the workflow in Xcode 11, but comes with one small limitation: we can not bundle resources with Swift packages. For Core Data this means that we can not include model files.
The solution is to create Core Data model programmatically. Let’s see how we can do this and the process can be improved.
TL;DR; I encountered this problem when I decided to create the index of downloaded images for my URLImage package. I came up with declarative approach and created a separate Swift package: CoreDataModelDescription to describe the model in code.
Core Data model in code
Core Data provides classes to describe the model in code, here are some:
NSEntityDescription
describes an entity in a model: name, list of properties, andNSManagedObject
class.NSPropertyDescription
describes a property of an entity: name, is it transient, is it optional. Property is a base for attributes and relationships.NSAttributeDescription
allows to specify a type, default value, and other features of an attribute in an entity.NSRelationshipDescription
describes relationships between two entities.
Both attribute and relationship are properties of an entity. There are more descriptions for sophisticated models. Consider this as minimum required to create feasible Core Data model.
Let’s take a simple model like this:
Model file (.xcdatamodeld
) is a package and model is actually described in XML:
We can follow it to describe the model in code. This routine by steps:
- Create
NSEntityDescription
objects and establish sub-super entity connections between them. - Create
NSAttributeDescription
for the fields that store data in your model. - Create
NSRelationshipDescription
s. Establish inverse relationships. - Fill properties on the entities with attributes and relationships.
NSManagedModel
can be created like this:
For the reference this is how NSManagedObject
subclasses look like:
As you can see the process is not hard but describing a model takes a lot of code. This is a good example of declarative (XML) vs imperative approaches.
Describing Core Data model in code
It’s a shame not to try declarative approach in code to solve the problem. Here is what I came up with:
I really like how Swift Package Manager uses Package.swift
file to describe a package so I decided to follow its format.
Describing Core Data mode declaratively feels natural and allows to focus on the model itself.
CoreDataModelDescription is available as a Swift package. Give it a try.
Cheers!