【SwiftUI】折れ線グラフを2つ表示する

# はじめに
SwiftUIのChartsで折れ線グラフを2つ表示させようとした時に苦戦したので記録しておきます。

# サンプルアプリ
![simulator_screenshot_DB3BA4F1-34EA-42AD-AAA1-773BD7E486DC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/25b897a7-8c8c-4672-ddc9-ad68fcad73e6.png)

# ダメな例
以下のように`LineMark`に`foregroundStyle`をつけることで色を変えることができます。
```swift
Chart {
    ForEach(temperatures, id: \.day) { temperature in
        LineMark(
            x: .value("day", temperature.day),
            y: .value("max", temperature.max)
        )
        .foregroundStyle(Color.orange)
    }
}
.frame(width: 300, height: 500)
```

![スクリーンショット 2024-01-11 22.30.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/214b9ebc-ae08-73e4-da95-085dad49da1b.png)

しかし、2つグラフを表示しようとしても、1つしか表示されません。
```swift
Chart {
    ForEach(temperatures, id: \.day) { temperature in
        LineMark(
            x: .value("day", temperature.day),
            y: .value("max", temperature.max)
        )
        .foregroundStyle(Color.orange)
        
        LineMark(
            x: .value("day", temperature.day),
            y: .value("min", temperature.min)
        )
        .foregroundStyle(Color.cyan)
    }
}
.frame(width: 300, height: 500)
```

![スクリーンショット 2024-01-11 22.31.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/689d8b4d-ceaa-60d7-f421-832144a81e47.png)

# 正しい実装
```diff_swift
import SwiftUI
import Charts

struct Temperature {
    let day: Int
    let max: Double
    let min: Double
}

struct ContentView: View {
    @State private var temperatures: [Temperature] = [
        .init(day: 1, max: 23, min: 13),
        .init(day: 2, max: 25, min: 10),
        .init(day: 3, max: 23, min: 11),
        .init(day: 4, max: 21, min: 11),
        .init(day: 5, max: 18, min: 12),
        .init(day: 6, max: 19, min: 13),
        .init(day: 7, max: 18, min: 15),
        .init(day: 8, max: 22, min: 9),
        .init(day: 9, max: 23, min: 10),
        .init(day: 10, max: 24, min: 13),
    ]
    
    var body: some View {
        Chart {
            ForEach(temperatures, id: \.day) { temperature in
                LineMark(
                    x: .value("day", temperature.day),
                    y: .value("max", temperature.max)
                )
+               .foregroundStyle(by: .value("max", "最高気温"))
                
                LineMark(
                    x: .value("day", temperature.day),
                    y: .value("min", temperature.min)
                )
+               .foregroundStyle(by: .value("min", "最低気温"))
            }
        }
+       .chartForegroundStyleScale(["最高気温": Color.orange, "最低気温": Color.cyan])
        .frame(width: 300, height: 500)
    }
}
```

# 解説
割とわかりにくいので解説します。
`foregroundStyle(by:)`を使用して、キーを指定します。
```swift
.foregroundStyle(by: .value("max", "ここの値がキー1"))
.foregroundStyle(by: .value("min", "ここの値がキー2"))
```

`foregroundStyle(by:)`で指定したキーを`chartForegroundStyleScale`で色とセットで渡します。
```swift
.chartForegroundStyleScale(["ここの値がキー1": Color.orange, "ここの値がキー2": Color.cyan])
```

このようにキーと色を紐付けることで2つのグラフが表示されるようになります。

:::note warn
`chartForegroundStyleScale`に存在しないキーを渡すとクラッシュします。
:::

# おわり
チャート用の機能がいっぱいあるのでちゃんとインプットしていかないと使いこなせなさそうです。