The types you can store in a Core Data persistent store are limited and it probably won't surprise you that UIColor objects are not supported out of the box.

You could use transformable attributes, but I prefer an alternative approach for storing colors. In this tutorial, I show you how to store UIColor objects in a Core Data persistent store. This is a topic we also we cover in Core Data Fundamentals.

Project Setup

Fire up Xcode and create a new project based on the iOS > Single View App template.

Project Setup

Name the project Colors and set Language to Swift. To save us some time, we also check Use Core Data at the bottom.

Project Setup

Save the project and select the data model of the project, Colors.xcdatamodeld. Create a new entity and name it Note. Add three attributes to the Note entity.

  • title of type String
  • contents of type String
  • colorAsHex of type String

Update Data Model

Each note can have a title, contents, and a color. As the name of the colorAsHex attribute suggests, we store the color as a string, a hex value. One of the advantages is that it's easy to debug. It's easier to read hex values than binary data. Right?

We don't stop here, though. We don't want to work with hex values. The goal is to only interact with UIColor instances. Converting a UIColor instance to a hex value and vice versa should be handled for us, automatically.

Extensions to the Rescue

As of Xcode 8, the class definition of the Note entity is automatically created for us. But we want to add some functionality to the Note class to make it easier to work with colors.

Extending UIColor

We first create an extension for the UIcolor class. In the extension, we define a convenience initializer for creating a UIColor instance from a hex value. I explain the implementation in more detail in another tutorial.

import UIKit
import Foundation

extension UIColor {

    // MARK: - Initialization

    convenience init?(hex: String) {
        var hexNormalized = hex.trimmingCharacters(in: .whitespacesAndNewlines)
        hexNormalized = hexNormalized.replacingOccurrences(of: "#", with: "")

        // Helpers
        var rgb: UInt32 = 0
        var r: CGFloat = 0.0
        var g: CGFloat = 0.0
        var b: CGFloat = 0.0
        var a: CGFloat = 1.0
        let length = hexNormalized.characters.count

        // Create Scanner
        Scanner(string: hexNormalized).scanHexInt32(&rgb)

        if length == 6 {
            r = CGFloat((rgb & 0xFF0000) >> 16) / 255.0
            g = CGFloat((rgb & 0x00FF00) >> 8) / 255.0
            b = CGFloat(rgb & 0x0000FF) / 255.0

        } else if length == 8 {
            r = CGFloat((rgb & 0xFF000000) >> 24) / 255.0
            g = CGFloat((rgb & 0x00FF0000) >> 16) / 255.0
            b = CGFloat((rgb & 0x0000FF00) >> 8) / 255.0
            a = CGFloat(rgb & 0x000000FF) / 255.0

        } else {
            return nil
        }

        self.init(red: r, green: g, blue: b, alpha: a)
    }
}

We also implement a computed property for converting a UIColor instance to its corresponding hex value.

import UIKit
import Foundation

extension UIColor {

    // MARK: - Initialization

    convenience init?(hex: String) {
        ...
    }

    // MARK: - Convenience Methods

    var toHex: String? {
        // Extract Components
        guard let components = cgColor.components, components.count >= 3 else {
            return nil
        }

        // Helpers
        let r = Float(components[0])
        let g = Float(components[1])
        let b = Float(components[2])
        var a = Float(1.0)

        if components.count >= 4 {
            a = Float(components[3])
        }

        // Create Hex String
        let hex = String(format: "%02lX%02lX%02lX%02lX", lroundf(r * 255), lroundf(g * 255), lroundf(b * 255), lroundf(a * 255))

        return hex
    }

}

Extending Note

The last piece of the puzzle is surprisingly easy. We create an extension for the Note class and define a computed property, color, of type UIColor?.

import UIKit
import Foundation

extension Note {

    var color: UIColor? {}

}

We implement the getter and setter of the computed property to convert the value of the colorAsHex property. In the getter, we convert the value of the colorAsHex property to a UIColor instance. We use the convenience initializer we implemented earlier.

import UIKit
import Foundation

extension Note {

    var color: UIColor? {
        get {
            guard let hex = colorAsHex else { return nil }
            return UIColor(hex: hex)
        }
    }

}

In the setter, we convert the new value of the computed property to a string using the toHex computed property we implemented a moment ago. We store the converted value in the colorAsHex property.

import UIKit
import Foundation

extension Note {

    var color: UIColor? {
        get {
            ...
        }
        set(newColor) {
            if let newColor = newColor {
                colorAsHex = newColor.toHex
            }
        }
    }

}

The result is that we don't directly access the colorAsHex property of the Note class. Instead, we use the color computed property as a proxy. The color computed property is in charge of value conversion.

// Getting a Color
let color = note.color

// Setting a Color
note.color = UIColor(hex: "FF5F5B")

What About Transformable Attributes

Transformable attributes are another option and, depending on the project, it may be a better solution. I cover transformable attributes in a future tutorial.

If you are serious about Core Data, then you should take a look at Core Data Fundamentals. In this book/course, we cover everything you need to know to integrate Core Data in your Swift projects.