How to save enum to Core Data
With a bit of help of computed property, we can save enumerations into Core Data quite easily!
Published: March 28, 2021 Sponsored I want a Press KitCore Data is great solution for persisting you application data. And while it can save all the primitive types including dates, UUIDs or even binary data. Enums are not included. This makes sense, because enums can take many forms.
In this post I will show you how we can work around that. Let's imagine we have simple Task
model which tracks the actual to-do and also its priority.
We want to model priority as an enum like this:
enum Priority {
case high
case standard
case trivial
}
And our Task
looks like this:
@objc(Task)
class Task: NSManagedObject {
@NSManaged var id: UUID
@NSManaged var text: String
override func awakeFromInsert() {
super.awakeFromInsert()
id = UUID()
}
}
And of course it has corresponding entry in the .xcdatamodeld
file.
Using private property to store the value
We can make this enum an Int
behind the scenes:
enum Priority: Int {
case high
case standard
case trivial
}
This will give us an access to the rawValue
and init
that takes an Int
.
We can privately use this Int
to save it into the database while on the outside expose just the Priority
.
@objc(Task)
class Task: NSManagedObject {
@NSManaged var id: UUID
@NSManaged var text: String
@NSManaged fileprivate var priorityValue: Int
var priority: Priority {
get {
return Priority(rawValue: priorityValue) ?? .standard
}
set {
priorityValue = newValue.rawValue
}
}
}
And that's it. The Task
exposes just the enum
to the outside world and its value is stored in the database.
This line:
return Priority(rawValue: priorityValue) ?? .standard
Could just use !
because the only way we are setting the priorityValue
is from the value of the Priority
enum. However if you were in the future to remove cases from the enum, then that would crash. 💥
While other types like UIImage
can also be saved using the "Transformable" type which let's you define custom value transformer, this is not the case for an enums, because they cannot be represented in Objective-C.
The "Transformable" approach involves creating custom class, which you can then set in the .xcdatamodeld
editor. In the case of UIImage
you would use this to convert it into Data
and back. Because Data
can be stored in Core Data database.
Or you could use this approach above and have private Data
attribute and computed property for the image which would do the conversion.
While the Transformable approach is probably more "correct", the computed property approach has the benefit of being pretty straightforward.
Uses: Xcode 12 & Swift 5.3