[iOS 14] Widgetでカウントダウン

WidgetのViewを更新するにはTimelineProviderプロトコルのgetTimelineメソッドを実装してタイムラインという何時何分にどんなデータでViewを更新するのかをあらかじめWidgetKitに伝える必要があります。

Todoアプリなどでイベントをカウントダウン表示したい場合を想定します。
毎秒更新するようにタイムラインを作成すればうまくいくかと思いきや、各アプリによってWidgetを更新できる回数は決まっています。

TimelineProviderのドキュメントにはこう書かれています。

Each configured widget receives a limited number of refreshes every day. Several factors affect how many refreshes a widget receives, such as whether the containing app is running in the foreground or background, how frequently the widget is shown onscreen, and what types of activities the containing app engages in.
それぞれのWidgetが毎日更新できる回数には限りがあります。何回Widgetを更新できるかは様々な要因があります。Widgetが含まれるアプリがフォアグラウンドで実行されているか、バックグラウンドで実行されているか、Widgetが画面に表示される頻度、または含まれているアプリが実行するアクティビティの種類などです。(筆者訳)

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

なのでタイムラインを毎秒作成するのはシステムが更新をブロックするのでよい手ではありません。

ではどうすればいいでしょうか?

幸い、iOS 14からTextViewにDate型を表示できるようになりました。
Textにカウントダウンしたい分だけ未来のDate型のインスタンスを渡して、style.timerを指定すれば、毎秒カウントダウンしているような表示になります。

コードはこんな感じ。

HStack {
    let components = DateComponents(minute: 15)
    let futureDate = Calendar.current.date(byAdding: components, to: Date())!

    Text("timer")
    Text(futureDate, style: .timer)
}

するとビルドすると毎秒カウントダウンします。

Widgetでカウントダウン表記をしたい場合は、タイムラインを毎秒作るのではなく、TextDateインスタンスを渡しましょう。

検証環境

  • iOS 14.2
  • Xcode 12.2 beta4

参考

宣伝

インプレスR&D社より、「1人でアプリを作る人を支えるSwiftUI開発レシピ」発売中です。
「SwiftUIでアプリを作る!」をコンセプトにSwiftUI自体の解説とそれを組み合わせた豊富なサンプルアプリでどんな風にアプリ実装すればいいかが理解できる本となっています。
iOS 14対応、Widgetの作成も一章まるまるハンズオンで解説しています。
SwiftUIを学びたい方、ぜひこちらのリンクをチェックしてください!




https://nextpublishing.jp/book/12491.html