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

Core 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

Filip Němeček profile photo

WRITTEN BY

Filip Němeček @nemecek_f

iOS blogger and developer with interest in Python/Django. My recent projects include IndieAppsCatalog and ImpressKit.

iOS blogger and developer with interest in Python/Django. My recent projects include IndieAppsCatalog and ImpressKit.