【Swift】Realmで配列データを更新する

# はじめに
RealmのListのデータ更新で躓いたので備忘録的に、雑にまとめておきます。

# 保存するデータ

- Gyudonyaクラスの中に複数のMenuクラスを持つようにします。

```
class Gyudonya: Object {
    @objc dynamic var storeName = ""
    var menus = List<Menu>()
}

class Menu: Object {
    @objc dynamic var name = ""
}
```

# データの保存方法
- 以下のように書いてデータをとりあえず保存します
```
      @IBAction private func tappedSaveButton(_ sender: Any) {
        do {
            let realm = try Realm()
            let gyudonya = Gyudonya(value: [
                "storeName": "吉野家",
                "menus": [
                    ["name": "牛丼"],
                    ["name": "ネギ玉牛丼"]
                ]
            ])
            try realm.write {
                realm.add(gyudonya)
                print("保存成功")
                print(gyudonya)
            }
        } catch {
            print("エラー")
        }
    }
```
- 出力結果はこんな感じ
```
保存成功
Gyudonya {
	storeName = 吉野家;
	menus = List<Menu> <0x600003d408f0> (
		[0] Menu {
			name = 牛丼;
		},
		[1] Menu {
			name = ネギ玉牛丼;
		}
	);
}
```

# データの更新方法
- 以下のように書くとデータを更新できます

```
    @IBAction private func tappedUpdateButton(_ sender: Any) {
        do {
            let realm = try Realm()
            var result = realm.objects(Gyudonya.self)

            let data = [
                ["name": "三種のチーズ牛丼"],
                ["name": "クランブルチーズケーキ"]
            ]

            try realm.write {
                result.first?.storeName = "すき家"
                result.first?.setValue(data, forKey: "menus")
                print("更新成功")
            }
        } catch {
            print("更新失敗")
        }
    }
```
- 保存後にデータを取得すると以下のようになっています

```
Gyudonya {
	storeName = すき家;
	menus = List<Menu> <0x600003d44210> (
		[0] Menu {
			name = 三種のチーズ牛丼;
		},
		[1] Menu {
			name = クランブルチーズケーキ;
		}
	);
}
```
## 注意するところ
- Listではない値(今回ではstoreName)であれば、以下のようにプロパティに直接更新したいデータを代入することで、値が書き変わります。
```
  result.first?.storeName = "すき家"
```
- しかし、Listを更新するときは上記のようなノリでは値を更新することができません。
- 以下のような書き方では値が更新されないってことですね。
- 以下のコードも実行すると"更新成功"出力はされますが、実際にはデータは書きかわりません。
```
         let realm = try Realm()
         var result = realm.objects(Gyudonya.self)

         let data = List<Menu>()
         let menu1 = Menu()
         menu1.name = "三種のチーズ牛丼"
         let menu2 = Menu()
         menu2.name = "クランブルチーズケーキ"

         data.append(objectsIn: [menu1, menu2])

         try realm.write {
             result.first?.storeName = "すき家"
             result.first?.menus = data
             print("更新成功")
         }
```
- そこで、前述のよう`setValue`を使います。
- 以下のような感じです。これでめでたくListの値を更新することができます
```
        let realm = try Realm()
        var result = realm.objects(Gyudonya.self)

        let data = [
             ["name": "三種のチーズ牛丼"],
             ["name": "クランブルチーズケーキ"]
         ]
         try realm.write {
             result.first?.storeName = "すき家"
             result.first?.setValue(data, forKey: "menus")
             print("更新成功")
         }
```

# おわりに
またどこかで自分が躓きそうだったのでまとめておきました。
どなたかの役に立てれば幸いでございますー。

一応今回書いたサンプルコードも載せておきます！！
ではでは！！

# サンプルコード

```
import UIKit
import RealmSwift

class Gyudonya: Object {
    @objc dynamic var storeName = ""
    var menus = List<Menu>()
}

class Menu: Object {
    @objc dynamic var name = ""
}

class ViewController: UIViewController {

    @IBAction private func tappedSaveButton(_ sender: Any) {
        do {
            let realm = try Realm()
            let gyudonya = Gyudonya(value: [
                "storeName": "吉野家",
                "menus": [
                    ["name": "牛丼"],
                    ["name": "ネギ玉牛丼"]
                ]
            ])
            try realm.write {
                realm.add(gyudonya)
                print("保存成功")
                print(gyudonya)
            }
        } catch {
            print("エラー")
        }
    }

    @IBAction private func tappedOutputButton(_ sender: Any) {
        do {
            let realm = try Realm()
            let results = realm.objects(Gyudonya.self)
            print("出力")
            for result in results {
                print(result)
            }
        } catch {
            print("失敗失敗")
        }
    }

    @IBAction private func tappedDeleteButton(_ sender: Any) {

        do {
            let realm = try Realm()

            try realm.write {
                realm.deleteAll()
                print("削除成功")
            }
        } catch {
            print("削除失敗")
        }
    }

    @IBAction private func tappedUpdateButton(_ sender: Any) {

        do {
            let realm = try Realm()
            var result = realm.objects(Gyudonya.self)

            let data = [
                ["name": "三種のチーズ牛丼"],
                ["name": "クランブルチーズケーキ"]
            ]

            try realm.write {
                result.first?.storeName = "すき家"
                result.first?.setValue(data, forKey: "menus")
                print("更新成功")
            }
        } catch {
            print("更新失敗")
        }
    }
}

```