Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I save a UIColor with UserDefaults? [duplicate]

I'm trying to program my code so that if the user presses the Night Button the background will turn black and stay black if the user closes the app. (Same goes for day mode.)

Please note: I already coded buttons and when they press it, all of the scenes change to that mode.

Here's my code where I'm going going to need the background color to be saved: (I need it in both if statements)

if GlobalData.dayBool == true && GlobalData.night == false {
    backgroundColor = GlobalData.dayColor 
}

if GlobalData.nightBool == true && GlobalData.dayBool == false {
    backgroundColor = GlobalData.nightColor 
}

My Night and Day Colors:

struct GlobalData {
    static var score = 0
    static var dayColor = UIColor(red:0.93, green:0.93, blue:0.93, alpha:1.0)
    static var nightColor = UIColor(red:0.10, green:0.10, blue:0.10, alpha:1.0)  
    static var dayBool = true
    static var nightBool = true
}
like image 887
Josh Schlabach Avatar asked Dec 19 '15 01:12

Josh Schlabach


People also ask

How do you save Uicolor in UserDefaults?

The easiest way would be using NSUserDefaults . In this case you are storing the string "Coding Explorer" and you can reference by the key "userNameKey" .

Can I save an object in UserDefaults?

UserDefaults can simply save custom object which conforms to Codable protocol. JSONEncoder and JSONDecoder play important roles for handling the data transformation. Nested object must also conform to Codable protocol in order to encode and decode successfully.

How do you save a string in UserDefaults?

To store the string in the user's defaults database, which is nothing more than a property list or plist, we pass the string to the set(_:forKey:) method of the UserDefaults class. We also need to pass a key as the second argument to the set(_:forKey:) method because we are creating a key-value pair.

Can you store a date in UserDefaults?

You can use UserDefaults to store any basic data type for as long as the app is installed. You can write basic types such as Bool , Float , Double , Int , String , or URL , but you can also write more complex types such as arrays, dictionaries and Date – and even Data values.


1 Answers

Swift 5.2 or later

Note that this will save only the RGBA CGFloat values as Data inside the property list. This will use 32 bytes (raw data) instead of 424 bytes needed when using the standard approach with NSKeyedUnarchiver (NSCoding):

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") }
    }
}

UserDefaults.standard.backgroundColor = .red
UserDefaults.standard.backgroundColor  // r 1.0 g 0.0 b 0.0 a 1.0
like image 166
Leo Dabus Avatar answered Oct 11 '22 17:10

Leo Dabus