📚
WidgetKitを学ぶ
これはなに
WidgetKit
について勉強した内容をまとめたもの。
定期的に更新する予定。
WidgetKitの使い方を俯瞰する
Appleのドキュメント を読み進める。
Rootで WidgetConfiguration
を生成して Widget
を構築していく。
WidgetConfiguration
には、
-
StaticConfiguration
: ユーザーがカスタマイズ不可のWidget
-
IntentConfiguration
: ユーザーがカスタマイズ可能なWidget
の2つがある。StaticConfiguration
の場合を例に全体像を把握する。
サンプルコードと解釈
@main
struct GameStatusWidget: Widget {
var body: some WidgetConfiguration {
StaticConfiguration(
kind: "com.mygame.game-status",
provider: GameStatusProvider(),
) { entry in
GameStatusView(entry.gameStatus)
}
.configurationDisplayName("Game Status")
.description("Shows an overview of your game status")
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge, .systemExtraLarge])
}
}
Widget
にコンテンツが表示されるまでの流れは、こんな感じ。
-
GameStatusProvider
がWidget
に表示するコンテンツのリストを時系列順に生成する -
StaticConfiguration
のinitializerのクロージャーが呼ばれて、コンテンツが順に渡される - 上記のクロージャー内でViewが生成されて、ユーザーに表示される
上記の流れで出てきたコンテンツのリストを Timeline
、1つのコンテンツを TimelineEntity
と呼ぶ。
最後にmodifierで Widget
の設定をする。
- configurationDisplayName: 表示名
- description:
Widget
の説明 - supportedFamilies:
Widget
のサイズ
ここまでできたら後は、 Provider
と View
を実装していく。
Providerの実装
Provider
についてまとめると、
-
Widget
で表示するTimeline
を生成する。-
Timeline
の要素は、TimelineEntity
を継承する
-
-
Provider
はTimelineEntity
を継承する - Widgetの一覧に表示する際のpreview用にsnapshotを渡す必要があって、
getSnapshot(in:completion:)
を使う -
getSnapshot(in:completion:)
が呼ばれてpreview用のsnapshotを渡した後に、getTimeline(in:completion:)
が呼ばれて実データを渡す
getSnapshot(in:completion:)のサンプルと注意点
struct GameStatusEntry: TimelineEntry {
var date: Date
var gameStatus: String
}
struct GameStatusProvider: TimelineProvider {
var hasFetchedGameStatus: Bool
var gameStatusFromServer: String
func getSnapshot(in context: Context, completion: @escaping (Entry) -> Void) {
let date = Date()
let entry: GameStatusEntry
if context.isPreview && !hasFetchedGameStatus {
entry = GameStatusEntry(date: date, gameStatus: "—")
} else {
entry = GameStatusEntry(date: date, gameStatus: gameStatusFromServer)
}
completion(entry)
}
}
context.isPreview = true
の時に、Widget一覧に表示される。
getTimeline(in:completion:)のサンプルとメモ
struct GameStatusProvider: TimelineProvider {
func getTimeline(in context: Context, completion: @escaping (Timeline<GameStatusEntry>) -> Void) {
// Create a timeline entry for "now."
let date = Date()
let entry = GameStatusEntry(
date: date,
gameStatus: gameStatusFromServer
)
// Create a date that's 15 minutes in the future.
let nextUpdateDate = Calendar.current.date(byAdding: .minute, value: 15, to: date)!
// Create the timeline with the entry and a reload policy with the date
// for the next update.
let timeline = Timeline(
entries:[entry],
policy: .after(nextUpdateDate)
)
// Call the completion to pass the timeline to WidgetKit.
completion(timeline)
}
}
getTimeline(in:completion:)
で実装するのは下記の2つ。
-
Widget
に表示するコンテンツデータを生成- 必要に応じてサーバーと通信したりする
- 更新する時のポリシーを指定する
WidgetのContentに関する注意点
基本的は View
に関してはSwiftUIで実装していくだけだが注意点がある。
最後に
Widget
に関して公式のリファレンスを読んで理解した内容をまとめました。
解釈が間違ってる可能性は十分にあるので、間違ってる点はコメントいただけると助かります。
今後も勉強した内容を追記していきます!
Discussion