WidgetKit入門
About
本記事では,Appleが提供するiOS,iPadOS向けのWidgetKitについてざっくりまとめます.WidgetKitは基本的にSwiftUIでViewを書かなければならないので,本記事を読む前にSwiftUIチュートリアルなどでSwiftUIを学習することを推奨します.
実行環境
開発環境
Environment | Version |
---|---|
MacBook Pro | 13-inch, 2017 |
macOS Monterey | 12.3.1 |
Xcode | 13.3.1 |
実機デモ
Environment | Version |
---|---|
iPhone | 12 Pro |
iOS | 15.4.1 |
Environment | Version |
---|---|
iPad Pro | 12.9-inch (4th) |
iPadOS | 15.4.1 |
Widgetの追加
まずはじめに,ウィジェットをアプリのTargetに追加しましょう.File -> New -> Target を選択します.
File -> New -> Target
iOSの項目からWidget Extensionを選択しましょう.Widgetの表示名は設定で変更できるので,Product NameはAppと名称が被らないようにすればなんでも大丈夫です.
Widget Extensionを選択
最後にTargetをActivateしたら追加完了です.
Activateを選択
それでは,試しにビルド(もしくはPreview)してみましょう.おそらく現在時刻を表示するViewが表示されたと思います.WidgetKitでは主に,表示されるデータをfunc getTimeline
で,表示されるViewをSwiftUIのvar body: some View {}
内で記述していきます.
func placeholder
ウィジェットがロードされる前に表示されるデータです.仮データ的な感じで捉えてもらえばいいです.
func getSnapshot
現在時刻のデータを作成してViewとして表示させるタイムラインエントリを作成します.ユーザがウィジェットを追加して最初に目にするViewのデータはここになります.ウィジェットのサイズを選択する画面で表示されるViewもここのデータで決まるので,それを意識してコーディングしましょう.
func getTimeline
現在と(オプションで)将来の時刻のデータの配列を作成して,いつそのデータを使ったViewを表示したいのかについてのタイムラインエントリの生成をします.基本的にここでウィジェットの内部データを作成していきます.
Timelineの頻度
WidgetKitは,快適な動作のために幾つかの制限を設けています.そのひとつがTimelineによる更新頻度です.15分に1度ウィジェットを更新するのがAppleの推奨最短更新頻度です.ウィジェットは1日に更新して良い回数の予算が決まっています.これ以上短い頻度での更新はOS側から制限される場合があるので推奨しません.
タイムラインの更新頻度は,func getTimeline
で以下のように記述して下さい.ちなみにタイムラインで生成するのは24時間分にしておくのがいいらしいです.
// 15分間隔での更新要求をするTimelineを生成
let currentDate = Date()
let futureDate = Calendar.current.date(byAdding: .minute, value: 15, to: currentDate)!
// 15 min * 96 times = 24 hours
for hourOffset in 0 ..< 96 {
// ここに処理を書く
entries.append(entry)
}
// 更新タイムラインの申請
let timeline = Timeline(entries: entries, policy: .after(futureDate))
completion(timeline)
ウィジェットの更新方法はTimeline以外にもいくつか存在しますが,本記事では省略します.また,ウィジェットの更新の予算は動的に変化するため,15分より短い頻度で行うことも可能な場合があります.詳しくは公式ドキュメントをご覧ください.
ウィジェットのサイズ(pt)を取得する
ウィジェットのサイズは端末の画面サイズによって異なります.通常のアプリであればUIScreen
を使って本体の画面サイズ(pt)を取得することで実装できます.
// iPhone 12 Pro
let screenSize = UIScreen.main.bounds.size
print(screenSize) // (390x844)
しかし,この方法だとウィジェットだけでなくホーム画面全体のサイズになってしまうので,以下の方法でウィジェットのViewのみのサイズ(pt)を取得しましょう.
let displaySize: CGSize
width
)で横方向,第2引数(height
)で縦方向のサイズ(pt)を指定することが可能です.数値の型はDouble
,Int
,CGFloat
として扱えます.内部の値としてはCGFloat
で保存されているため,計算などの場合は気をつけて下さい.
ウィジェットのサイズ別のViewを設定する
WidgetKitには,iOSで3種類(小・中・大),iPadOSで4種類(小・中・大・極大)のサイズが用意されています.サイズによって違うViewを表示させることでウィジェットが一層使いやすく,スタイリッシュになるので是非実装してみて下さい.
ウィジェットのサイズは環境変数で取得できます.
@Environment(\.widgetFamily) var family: WidgetFamily
.systemSmall
,.systemMedium
,.systemLarge
,.systemExtraLarge
で分岐させることでそれぞれ別のViewを表示できます.戻り値がViewな関数をそれぞれ呼び出すのがおすすめです.
あとがき
最近ウィジェットのあるアプリの開発をしたのですが,WidgetKitに関する記事を探すのに苦労したので,個人的に必要になった知識をApple公式ドキュメントに沿ってまとめました.記事にまとめるのは初めてなので,拙い部分が多々あるかもしれません.
placeholder
,getSnapshot
,getTimeline
の辺りは本記事を執筆して理解が深まったので,アウトプットって思ってた以上に大切ですね.ちなみに検索する時は”Widget”ではなく”WidgetKit”で検索した方が,調べたかった内容に辿り着きやすくなると思います.
本記事が誰かのお役に立てば幸いです.役に立ったら記事のお気に入り登録とFollowしてくれると嬉しいです.
Discussion