LoginSignup
0
2

More than 3 years have passed since last update.

SwiftUI ColorをUserDefaultsで永続化する方法

Last updated at Posted at 2021-04-29

目的

 SwiftUIで背景のColorを永続化したいことがありましたが、iOS14+のコードが多く、iOS13に対応した動くコードが見つからなかったので、メモしておきます。

コード

 Extensionで汎用化する必要がなかったので、メソッドで定義しています。また、UserDefaultsの実装はインターネット上に例が多いので、ここでは詳細は省略します。

ColorをUserDefaultsに保存する場所
func colorHandler(_ color: Color){
        var persistenceData = UserDefault_Keys()
        if #available(iOS 14.0, *) {
            if let components = color.cgColor?.components {
                persistenceData.advBgColorR = Double(components[0])
                persistenceData.advBgColorG = Double(components[1])
                persistenceData.advBgColorB = Double(components[2])
                persistenceData.advBgColorA = Double(components[3])
            }
        } else {
            let description = color.description
            let elements: [String] = description.components(separatedBy: " ")
            var r: Double = 0.0, g: Double = 0.0, b: Double = 0.0, a: Double = 0.0

            if color == Color.white {
                r = 1.0
                g = 1.0
                b = 1.0
                a = 1.0
            } else if color == Color.black {
                r = 0.0
                g = 0.0
                b = 0.0
                a = 1.0
            } else {
                r = Double(elements[1]) ?? 0.0
                g = Double(elements[2]) ?? 0.0
                b = Double(elements[3]) ?? 0.0
                a = Double(elements[4]) ?? 0.0
            }
            persistenceData.advBgColorR = r
            persistenceData.advBgColorG = g
            persistenceData.advBgColorB = b
            persistenceData.advBgColorA = a
        }
    }

【ポイント1】iOS14+ではcgColorが使えるが、iOS13では使えない(将来的にiOS13がアプリのサポート対象外となれば、実装が簡潔になる)
【ポイント2】color.descriptionは、システムカラー(Color.whiteなど)の場合は、[UIExtendedSRGBColorSpace 1 1]などと書式が異なりRGB値を取得できないので、条件分岐が必要(ここの例では、メソッドの引数になるシステムカラーが白か黒だけの想定)。なお、システムカラー以外の場合は、UIExtendedSRGBColorSpace 0.839216 0.521569 0.690196 1のような値になる

UserDefaultsから取り出す場所
let persistenceData = UserDefault_Keys()
let color = Color(red: persistenceData.advBgColorR, green: persistenceData.advBgColorG, blue: persistenceData.advBgColorB, opacity: persistenceData.advBgColorA)
UserDefaultsのハンドラー
import SwiftUI

@propertyWrapper
struct UserDefault<T> {
    let key: String
    let defaultValue: T
    var wrappedValue: T {
        get {
            return UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
        }
        set {
            UserDefaults.standard.set(newValue, forKey: key)
        }
    }
}

struct UserDefault_Keys {
    @UserDefault(key: "Adv_bgColor_R", defaultValue: 0.0)
    var advBgColorR: Double

    @UserDefault(key: "Adv_bgColor_G", defaultValue: 0.0)
    var advBgColorG: Double

    @UserDefault(key: "Adv_bgColor_B", defaultValue: 0.0)
    var advBgColorB: Double

    @UserDefault(key: "Adv_bgColor_A", defaultValue: 0.0)
    var advBgColorA: Double
}

参考リンク

Handling Colors in SwiftUI
How can I change a SwiftUI Color to UIColor? *コメントにある通り、正常に動きませんが参考にはなる
[SwiftUI] SwiftUI の Color を UserDefaults に保存する *ライブラリ使用、iOS14+
UserDefaultsをProperty Wrapperでカッコよく使う
Save/Get UIColor from UserDefaults

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2