watchOS7時代のコンプリケーション


## 注意
ベータ版は色々バグや不安定な箇所がありますのでご注意ください。
Appleにフィードバックを送ってより良いものにしていきましょう😌

## **環境**

- watchOS 7 beta
- Xcode 12 beta

## Build complications in SwiftUI
<figure id = "">
<img width="969" alt="スクリーンショット 2020-07-06 15.17.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171702/665555c4-8e28-73f0-defe-8d8fd45efc8a.png">
<figcaption>[引用: Get ready for watchOS 7.]</figcaption>
</figure>
- SwiftUIでwatchOSのコンプリケーションが作れるようになった
- コンプリケーションとは、アプリに関するタイムリーで関連性の高い情報をウォッチフェイスに表示
- 複雑な情報をひと目で理解できるものに洗練することができる

## 追加されたSwiftUIで使えるComplication Template
Graphic Corner, Circular, Rectangular, and Extra Largeの4つ

- GraphicCorner
    - [`CLKComplicationTemplateGraphicCornerCircularView`](https://developer.apple.com/documentation/clockkit/clkcomplicationtemplategraphiccircularview)
    - [CLKComplicationTemplateGraphicCornerGaugeView](https://developer.apple.com/documentation/clockkit/clkcomplicationtemplategraphiccornergaugeview?language=objc)
    - [CLKComplicationTemplateGraphicCornerTextView](https://developer.apple.com/documentation/clockkit/clkcomplicationtemplategraphiccornertextview?language=objc)

- GraphicCircular
    - [`CLKComplicationTemplateGraphicCircularView`](https://developer.apple.com/documentation/clockkit/clkcomplicationtemplategraphiccircularview)
    - [CLKComplicationTemplateGraphicCircularStackViewText](https://developer.apple.com/documentation/clockkit/clkcomplicationtemplategraphiccircularstackviewtext)
    - [CLKComplicationTemplateGraphicCircularClosedGaugeView](https://developer.apple.com/documentation/clockkit/clkcomplicationtemplategraphiccircularclosedgaugeview)
    - [CLKComplicationTemplateGraphicCircularOpenGaugeView](https://developer.apple.com/documentation/clockkit/clkcomplicationtemplategraphiccircularopengaugeview)

- GraphicRectangular
    - [`CLKComplicationTemplateGraphicRectangularFullView`](https://developer.apple.com/documentation/clockkit/clkcomplicationtemplategraphicrectangularfullview)
    - [CLKComplicationTemplateGraphicRectangularLargeView](https://developer.apple.com/documentation/clockkit/clkcomplicationtemplategraphicrectangularlargeview)
    - [CLKComplicationTemplateGraphicRectangularTextGaugeView](https://developer.apple.com/documentation/clockkit/clkcomplicationtemplategraphicrectangulartextgaugeview)
    - [CLKComplicationTemplateGraphicRectangularStandardBodyView](https://developer.apple.com/documentation/clockkit/clkcomplicationtemplategraphicrectangularstandardbodyview)

- ExtraLargeCircular
    - [`CLKComplicationTemplateGraphicExtraLargeCircularView`](https://developer.apple.com/documentation/clockkit/clkcomplicationtemplategraphicextralargecircularview)
    - [CLKComplicationTemplateGraphicExtraLargeCircularStackViewText](https://developer.apple.com/documentation/clockkit/clkcomplicationtemplategraphicextralargecircularstackviewtext)
    - [CLKComplicationTemplateGraphicExtraLargeCircularClosedGaugeView](https://developer.apple.com/documentation/clockkit/clkcomplicationtemplategraphicextralargecircularclosedgaugeview)
    - [CLKComplicationTemplateGraphicExtraLargeCircularOpenGaugeView](https://developer.apple.com/documentation/clockkit/clkcomplicationtemplategraphicextralargecircularopengaugeview)

## 

## Preview
適当なViewをSwiftUIで作成します。
新しく追加されたAPIもコンプリケーションに使えるので便利ですね！

```swift
import SwiftUI
import ClockKit

struct SampleGraphicRectangular: View {
    @State var gaugeValue: CGFloat = 3
    var body: some View {
        VStack {
            Text("Swift愛好会")
            Gauge(value: gaugeValue, in: 1...15) {
                Image(systemName: "drop.fill")
                    .foregroundColor(.green)
            } currentValueLabel: {
                Text("\(gaugeValue, specifier: "%.1f")")
            }
            .gaugeStyle(LinearGaugeStyle(
                tint: Gradient(colors: [.orange, .yellow, .green, .blue, .purple])
            ))
        }
    }
}
```
これをプレビューしたいですね！
しかし、CLKComplicationテンプレートはSwiftUIのViewそのものではないので、単体ではプレビューすることができません。

そこで今回追加されたSwiftUI用の`CLKComplicationTemplate`と`previewContext`関数です！

`ClockKit`と`SwiftUI`の両方を同時にインポートした場合に利用することができます。

プレビューされた全てのComplicationテンプレートは、それらのfamilyに最適なwatch faceに設定されます。

以下のようなに適当なViewを作成し、 テンプレートを適用し`previewContext()`を利用すると

```swift
struct SampleGraphicRectangular_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            CLKComplicationTemplateGraphicCornerCircularView(SampleGraphicRectangular())
                .previewContext()

            CLKComplicationTemplateGraphicCircularView(SampleGraphicRectangular())
                .previewContext()

            CLKComplicationTemplateGraphicRectangularFullView(SampleGraphicRectangular())
                .previewContext()

            CLKComplicationTemplateGraphicExtraLargeCircularView(SampleGraphicRectangular())
                .previewContext()
        }
    }
}
```

以下のような対応されたwatch faceのプレビューを表示し自身のViewがコンプリケーションとして表示されていることをプレビューすることができます。
めちゃくちゃ便利です！！！

|            | CLKComplicationTemplate<br>GraphicCornerCircularView | CLKComplicationTemplate<br>GraphicCircularView | CLKComplicationTemplate<br>GraphicRectangularFullView | CLKComplicationTemplate<br>GraphicExtraLargeCircularView |
| ---------- | -------------- | -------- | --------------- | ---------- |
| preview<br>(イメージ)  |![infograph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171702/9ab1ece2-42b1-2b81-5ef8-3e8dc4dabc68.png)         | ![infomodular.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171702/7b7d47f3-729c-ab07-170f-6fdfe4028d0d.png) |![infomodular.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171702/7b7d47f3-729c-ab07-170f-6fdfe4028d0d.png)   |      ![extralarge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171702/f31481ef-d8cf-7dff-7f97-5e514f0ff828.png) |
| watch face |   インフォグラフ（左上）             |   インフォグラフモジュラー（小さい円）     |        インフォグラフモジュラー（中央）             |       特大（中央）     |


face color
以下のようなメソッドでwatch faceのカラーを変えることができます。

```swift
.previewContext(faceColor: .blue)
```

またwatch faceのfaceColorによってコンプリケーションの見た目を変更したい場合には以下のようにcomplicationのRenderingModeが環境変数から取れますのでそれを利用することで対応できます！

```swift
@Environment(\.complicationRenderingMode) var mode
```



## エラー

`ComplicationController`の`getCurrentTimelineEntry（）`などでComplication familyと異なるタイプのTemplateが選択されていた場合

```
Data handler called with incompatible template for complication family.
Expected template for 'CLKComplicationFamilyGraphicCircular',
but received one for 'CLKComplicationFamilyGraphicCorner'.
```

## できないこと
- SwiftUIのButton, gestures,その他のインタラクティブ要素はサポートされていない
    - Complicationはどこをタップしても必ずアプリが起動する
- SwiftUIのAnimationはサポートされていない
    - Complicationは静的なViewで構成されたタイムラインであること


## 参考
- [Build complications in SwiftUI
](https://developer.apple.com/videos/play/wwdc2020/10048/)
- [Get ready for watchOS 7.](https://developer.apple.com/jp/watchos/whats-new/)
- [Human Interface Guidelines Complications](https://developer.apple.com/design/human-interface-guidelines/watchos/overview/complications/)
- [Apple Watch の全11種類の Complication を確認できる Watch face の対応表](https://qiita.com/synboo/items/790f666eae0308d6d8cb)
- [Apple Watchの文字盤と機能](https://support.apple.com/ja-jp/guide/watch/apde9218b440/watchos)