［SwiftUI / WidgetKit］大きさが異なるウィジェットを設定する


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199441/686147e5-a3ab-adec-b310-5f49d721bb36.png" width=500>

## この記事の内容
- 大きさが異なるウィジェットを設定する

## 開発環境
|項目|内容|
|---|---|
|PC| MacBook Air （2020 M1）|
|言語|Swift|
|フレームワーク|SwiftUI|
|IDE|Xcode|
|コード管理|GitHub|

## コード
```swift:EmojisWidget.swift
import WidgetKit
import SwiftUI

struct Provider: TimelineProvider {
    
    func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> Void) {
        let entry = SimpleEntry(date: Date(), emoji: Emoji(icon: "💛", name: "N/A", description: "N/A"))
        completion(entry)
    }
    
    func getTimeline(in context: Context, completion: @escaping (Timeline<SimpleEntry>) -> Void) {
        let userDefaults = UserDefaults(suiteName: "group.sample.Emojis")!
        let date = Date()
        let emojiData = userDefaults.object(forKey: "Emoji") ?? Data()
        guard let emoji = try? JSONDecoder().decode(Emoji.self,from: emojiData as! Data) else {
            let entry = SimpleEntry(date: date, emoji: Emoji(icon: "💛", name: "N/A", description: "N/A"))
            let timeline = Timeline(entries: [entry], policy: .never)
            completion(timeline)
            return
        }
        let entry = SimpleEntry(date: date, emoji: emoji)
        let timeline = Timeline(entries: [entry], policy: .never)
        completion(timeline)
    }
    
    func placeholder(in context: Context) -> SimpleEntry {
        return SimpleEntry(date: Date(), emoji: Emoji(icon: "💛", name: "N/A", description: "N/A"))
    }
}

struct SimpleEntry: TimelineEntry {
    let date: Date
    let emoji: Emoji
}

struct EmojisWidgetEntryView : View {
    @Environment(\.widgetFamily) var family: WidgetFamily
    
    var entry: Provider.Entry

    var body: some View {
        switch family {
        case .systemSmall:
            EmojisWidgetSmallView(emoji: entry.emoji)
        case .systemMedium:
            EmojisWidgetMediumView(emoji: entry.emoji)
        case .systemLarge:
            EmojisWidgetLargeView(emoji: entry.emoji)
        case .systemExtraLarge:
            EmojisWidgetLargeView(emoji: entry.emoji)
        }
            
    }
}

struct EmojisWidgetSmallView : View {
    var emoji: Emoji
    var body: some View {
        EmojiView(emoji: emoji)
    }
}

struct EmojisWidgetMediumView : View {
    var emoji: Emoji
    var body: some View {
        HStack {
            EmojiView(emoji: emoji)
            Text(emoji.name)
        }
    }
}

struct EmojisWidgetLargeView : View {
    var emoji: Emoji
    var body: some View {
        HStack {
            EmojiView(emoji: emoji)
            VStack(alignment: .leading){
                Text(emoji.name)
                Text(emoji.description)
            }
        }
    }
}

@main
struct EmojisWidget: Widget {
    let kind: String = "EmojisWidget"

    var body: some WidgetConfiguration {
        StaticConfiguration(kind: "Emojis_Widget", provider: Provider()) { entry in
            EmojisWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("Emojis Widget")
        .description("This is an example widget.")
        .supportedFamilies([.systemSmall,.systemMedium,.systemLarge,.systemExtraLarge])
    }
}

struct EmojisWidget_Previews: PreviewProvider {
    static var previews: some View {
        EmojisWidgetEntryView(entry: SimpleEntry(date: Date(), emoji: Emoji(icon: "💛", name: "N/A", description: "N/A")))
            .previewContext(WidgetPreviewContext(family: .systemSmall))
    }
}
```

## GitHub のコード

https://github.com/tanakadaichi1989/Emojis

## 注意事項
ウィジェットのうち `.systemExtraLarge` は iPad のみで利用可能

## 備考
- 上記スクリーンショットは、iPad （9th Generation） のもの

## 参考資料

https://developer.apple.com/documentation/widgetkit/widgetfamily