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

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

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

```swift: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
        }
    }
```

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

```swift:UserDefaultsから取り出す場所
let persistenceData = UserDefault_Keys()
let color = Color(red: persistenceData.advBgColorR, green: persistenceData.advBgColorG, blue: persistenceData.advBgColorB, opacity: persistenceData.advBgColorA)
```

```swift: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](https://betterprogramming.pub/handling-colors-in-swiftui-576e8f100d65)
[How can I change a SwiftUI Color to UIColor?　＊コメントにある通り、正常に動きませんが参考にはなる](https://stackoverflow.com/questions/57257704/how-can-i-change-a-swiftui-color-to-uicolor)
[[SwiftUI] SwiftUI の Color を UserDefaults に保存する　＊ライブラリ使用、iOS14+](https://software.small-desk.com/development/2021/01/18/swiftui-color-userdefaults-swiftyuserdefaults/#Color_UserDefaults-2)
[UserDefaultsをProperty Wrapperでカッコよく使う](https://qiita.com/ryotapoi/items/2f861f734a4d48aad487)
[Save/Get UIColor from UserDefaults](https://stackoverflow.com/questions/52999953/save-get-uicolor-from-userdefaults)