[Swift] UserDefaultsの使い方

#UserDefaultsとは
アプリ起動時にキーと値のペアを永続的に保存してくれます。
UserDefault classは、デフォルトシステムと対話するためのプログラム上のインターフェイスを提供してくれる
と、公式ドキュメントに載っていました。
このデフォルトシステムを使用すると、例えば、動画再生速度を自分好みに設定して（再生速度１.５倍速とか?）保存できます。
次にアプリを起動する際には、先程の設定がデフォルトになっているので、１.５倍速のままになっている訳です。
#デフォルトオブジェクトの保存
保存のメソッドは型ごとにあります。

```swift
func set(Any?, forKey: String)
//Sets the value of the specified default key.
func set(Float, forKey: String)
//Sets the value of the specified default key to the specified float value.
func set(Double, forKey: String)
//Sets the value of the specified default key to the double value.
func set(Int, forKey: String)
//Sets the value of the specified default key to the specified integer value.
func set(Bool, forKey: String)
//Sets the value of the specified default key to the specified Boolean value.
func set(URL?, forKey: String)
//Sets the value of the specified default key to the specified URL.
```

使い方としては、以下のように呼び出して値の型も指定します。
値の箇所には保存したい値を入れ、forKeyにはString型でKeyを設定します。
このKeyはデータを引っ張ってくる時に使用します。

```swift
 UserDefaults.standard.set(値, forKey:)
```
#保存された値の呼び出し
呼び出すメソッドも型ごとに存在しています。

```swift
func object(forKey: String) -> Any?
//Returns the object associated with the specified key.
func url(forKey: String) -> URL?
func array(forKey: String) -> [Any]?
func dictionary(forKey: String) -> [String : Any]?
func string(forKey: String) -> String?
func stringArray(forKey: String) -> [String]?
func data(forKey: String) -> Data?
func bool(forKey: String) -> Bool
func integer(forKey: String) -> Int
func float(forKey: String) -> Float
func double(forKey: String) -> Double
func dictionaryRepresentation() -> [String : Any]
```

これを使って、呼び出したい箇所で定数に入れたりして、コードを書きます。
forKeyには先程設定してKeyを入れる事で、それに紐付いものが取得できます。

```swift
UserDefaults.standard.string(forKey:)
```


#保存された値の変更
値として変更可能なものオブジェクトを設定した場合でも、UserDefaultsから返される値は不変になります。
変更可能なはずなのになぜ！となるかもしれませんが、これには理由があります。
UserDefaultsはset()で既定値を再度保存しないと、String（forKey）で呼び出しても保存前の既定値が呼び出されるという訳です。

実際に確かめてみました。


```swift
import UIKit

class ViewController: UIViewController {

    @IBOutlet var textField: UITextField!
    @IBOutlet var UserDefaultsLabel: UILabel!
    @IBOutlet var contentLabel: UILabel!
    var textContent = ""
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let immutable = UserDefaults.standard.string(forKey: "text")  //UserDefaultsから返された値（可変のものでも不変）。set()で再度呼び出さないと既定値として変更できない。
        UserDefaultsLabel.text = immutable
    }

    @IBAction func setButton(_ sender: Any) {
        UserDefaults.standard.set(textContent, forKey: "text") //既定値を変更している
    }
    
    @IBAction func hennkouButton(_ sender: Any) {
        textContent = textField.text!
        contentLabel.text = "textContentの値は\(textContent)"
    }
}
```

可変のプロパティの値を変更するボタンがhenkouButtonで、labelに変更内容が表示されます。
setButtonはUserDefaultsに既定値を保存する処置を行います。
henkouButtonを押しただけだと既定値は変更できていないので、その後viewDidLoadでUserDefaulesから値を取り出しても変更は反映されていません。
henkouButtonを押して、setButtonを押す事で既定値の変更が完了し、viewDidLoadで値の変更が行われてます。

#####henkouButtonだけの場合
初期値はUserDefaultsと表示されています。
１２３と入力してhenkouButtonを押してみます。変更内容が一番下のlabelに表示されています。
![スクリーンショット 2020-12-31 16.10.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/8b1f6646-cfbd-3b84-3a2f-263437f90c2c.png)


ここでsetButtonを押さずに、アプリを落としてみます。
既定値は変更されていないので、上のLabelはUserDefaultsのままです。
![スクリーンショット 2020-12-31 16.12.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/d90b8bbf-bc13-2100-adb5-9e083d3bdfff.png)
#####setButtonも押して、既定値を変更
既定値を変更して、アプリを落としてみると、、、
見事値が変更されました！
これで可変のものでも、変更した後にset()で既定値の変更を行わないと変更できないという事がわかりました。
![スクリーンショット 2020-12-31 16.15.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/4333e9a1-3e39-90f4-ec55-bab3b60d728b.png)

#参考サイト
https://developer.apple.com/documentation/foundation/userdefaults#1664798