Swift iOS – how to save UIColor in UserDefsults

Add the following extensions:

extension Numeric {
    var data: Data {
        var bytes = self
        return Data(bytes: &bytes, count: MemoryLayout<Self>.size)
    }
}
extension Data {
    func object<T>() -> T { withUnsafeBytes{$0.load(as: T.self)} }
    var color: UIColor { .init(data: self) }
}
extension UIColor {
    convenience init(data: Data) {
        let size = MemoryLayout<CGFloat>.size
        self.init(red:   data.subdata(in: size*0..<size*1).object(),
                  green: data.subdata(in: size*1..<size*2).object(),
                  blue:  data.subdata(in: size*2..<size*3).object(),
                  alpha: data.subdata(in: size*3..<size*4).object())
    }
    var rgba: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)? {
        var (red, green, blue, alpha): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
        return getRed(&red, green: &green, blue: &blue, alpha: &alpha) ?
        (red, green, blue, alpha) : nil
    }
    var data: Data? {
        guard let rgba = rgba else { return nil }
        return rgba.red.data + rgba.green.data + rgba.blue.data + rgba.alpha.data
    }
}
extension UserDefaults {
    func set(_ color: UIColor?, forKey defaultName: String) {
        guard let data = color?.data else {
            removeObject(forKey: defaultName)
            return
        }
        set(data, forKey: defaultName)
    }
    func color(forKey defaultName: String) -> UIColor? {
        data(forKey: defaultName)?.color
    }
}
extension UserDefaults {
    var backgroundColor: UIColor? {
        get { color(forKey: "backgroundColor") }
        set { set(newValue, forKey: "backgroundColor") }
    }
}

Usage

Set:

let defaults = UserDefaults.standard
defaults.backgroundColor = UIColor.systemOrange

Get (with default incase error):

let defaults = UserDefaults.standard
myView.backgroundColor = defaults.backgroundColor ?? UIColor.systemTeal

(Optional) Check if exists, else set:

let defaults = UserDefaults.standard
if let col = defaults.object(forKey: "backgroundColor") {
    //Color exists in UserDefaults
    myView.backgroundColor = defaults.backgroundColor ?? UIColor.systemTeal
}else{
    //Color NOT exists in UserDefaults
    defaults.backgroundColor = UIColor.systemOrange
}

Leave a comment