Help us understand the problem. What is going on with this article?

[iOS 14] Widgetの技術的要点をざっくり

Widgetはミニアプリではない

  • Widget上で操作することは想定されておらず、スクロールやインタラクティブなUI (e.g. Switch) や動画などはサポートされない
  • ただし、Widgetをタップするとディープリンクでアプリ内の適切な画面を開ける
    • Smallサイズは1つのリンクしか持てない
    • MediumとLargeサイズは複数のリンクを持つことができ、タップした領域によって別のディープリンクを開くことができる
      1つのWidgetに複数のリンク
      (Meet WidgetKit より)

画面は事前に描画される

  • 「Widgetを表示するタイミングでアプリを起動してロードして...」という読み込み時間がないのでWidgetの変更がすぐに反映される
    • ただし、初回表示時や設定変更時 (e.g. ダイナミックタイプの変更) には画面描画まで時間が掛かるのでPlaceholderが表示される
  • SwiftUIの宣言的にViewを定義できる性質を活かした仕組み
  • Timelineという仕組みによって画面更新のスケジューリングを行う

Widgetのバリエーション

  • 1つのアプリは複数種類のWidgetを持てる
    • 1つのアプリの中で複数の WidgetKit extension を持つこともできるが、1つの WidgetKit extension に複数Widgetをまとめることが推奨されている
    • WidgetBundle を使うことで1つの WidgetKit extension に複数のWidgetをまとめることができる
  • 1つのWidgetは複数のサイズを持てる
    • WidgetFamily に定義されている以下3種類がある
      • systemSmall
      • systemMedium
      • systemLarge
    • どれか1つのサイズだけサポートしても良い
  • 同じ種類・サイズのWidgetをホーム画面に複数個置ける
    • Widgetの設定を変えることで別の見た目にすることが可能

Smart Stack

  • 複数のWidgetを1つの枠にまとめられる機能
    Smart Stack
    (Design great widgets より)
  • 上下スワイプでWidget間を移動できる
  • システムがその時々で一番最適なWidgetを自動で判断して表示する
    • 以下の情報をアプリから提供するとより精度が上がる
      • Shortcuts donation
        • アプリ内のユーザー操作をSiriに伝える
      • 関連度 (Relevance)
        • TimelineEntry に対して score と duration を付与する
        • score の最大値と最小値は自由に決めて良い

パーソナライズ (Widget Configuration)

  • ホーム画面を編集モードにしてWidgetをタップするとWidgetの設定ができる
    Smart Stack
    (Design great widgets より)
  • Intents (i.e. SiriKitINIntent) を用いることで可能となる
    • SiriやShortcutsとの連携でも使われている技術
    • Intentsの情報から自動で設定画面のUIが作られる
    • ネットワークを通じて設定項目を取得するなどして動的に設定項目を変えることもできる

各キーワードについてもう少し詳しく

Timeline

  • いつ、どのようなViewを表示するかをあらかじめ計画する
  • Timelineの更新タイミング
    • システムによる更新
      • ReloadPolicy からシステムが更新に最適なタイミングを判断する
      • システムによってよく見られているWidgetだと判斷された場合はシステムがより頻繁に更新する
        • つまり ReloadPolicy 通りに更新されるわけではない?
    • アプリ起因による更新
      • WidgetCenter を通じて任意のタイミングで
        • アプリ本体からでも WidgetKit extension からでも
      • URLSession の background session が完了したタイミング
        • データをインターネットから取得してきた後など
        • 負荷を上げないために頻繁に更新しすぎないよう注意
  • 例外として、 Text viewのパラメーターにDate型を渡して日時を表示する場合は、意図的に更新しなくても随時最新の日時に更新される

Snapshot

  • 現在の日時や状態などの情報が含まれる TimelineEntry を元にしてそれに対応する画面を返す
  • パラメーターで渡される context.isPreview がtrueのときは Widget Gallery で使用される
    • Widget Gallery とは、ホーム画面にWidgetを追加する際に見本のWidgetが表示される画面
      Widget Gallery
      (Meet WidgetKit より)
    • 素早くユーザーに見本を提示する必要があるため、サーバーからデータを取得するWidgetの場合は代わりにサンプルデータを使う

Placeholder

  • 初回表示時や設定変更時 (e.g. ダイナミックタイプの変更) に、まだTimelineが作成されていないときに表示される
  • WidgetのViewに .isPlaceholder(true) を追加するだけで簡単に作成できる

参考資料

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away