Swift Academy · レッスン

タイムラインプロバイダーとスナップショット

時間の経過に応じてウィジェットのコンテンツを提供します。

レッスン 2/413 ステップ

「タイムラインプロバイダーとスナップショット」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。

プロバイダーの役割

Widgetが継続的に自分自身を更新することはありません。その代わり、TimelineProviderが事前に描画されたエントリのスケジュールをWidgetKitに渡し、システムがそれぞれを適切な時刻に表示します。プロバイダーは、プレースホルダー、スナップショット、タイムラインという3つの問いに答えます。

import WidgetKit
// TimelineProvider supplies:
//   placeholder(in:) -> instant skeleton
//   getSnapshot(in:)  -> one entry for previews
//   getTimeline(in:)  -> future entries + refresh policy

TimelineProviderへの準拠

プロバイダーはTimelineProviderに準拠し、関連するEntry型を指定します。3つのメソッドを実装すると、それぞれにファミリーとプレビューかどうかを示すContextが渡されます。

import WidgetKit
struct WeatherProvider: TimelineProvider {
    typealias Entry = WeatherEntry
    func placeholder(in context: Context) -> WeatherEntry {
        WeatherEntry(date: Date(),
            temperature: 20, condition: "Sunny")
    }
    // getSnapshot and getTimeline follow
}

プレースホルダー

placeholder(in:)は、代表的なダミーデータを即座に返す必要があります。システムは、実際のWidgetの読み込み中やWidgetギャラリーで、これをレダクションされたスケルトンとして表示します。ここではネットワークやディスクへのアクセスを決して行わないでください。

import WidgetKit
func placeholder(in context: Context) -> WeatherEntry {
    // Synchronous, fake data, no I/O
    WeatherEntry(date: Date(),
        temperature: 0, condition: "--")
}

スナップショット

getSnapshotは、Widgetギャラリーのプレビューなど、一時的な状況に対して単一のエントリを提供します。すぐに返す必要があります。context.isPreviewがtrueの場合は、ギャラリーを瞬時に表示できるよう、時間のかかる取得処理ではなくサンプルデータを使用してください。

import WidgetKit
func getSnapshot(
    in context: Context,
    completion: @escaping (WeatherEntry) -> Void) {
    if context.isPreview {
        completion(WeatherEntry(date: Date(),
            temperature: 22, condition: "Clear"))
    } else {
        completion(currentEntry())
    }
}

タイムライン

getTimelineが中心となる処理です。将来のエントリの配列を作成し、更新ポリシーとともにTimelineにまとめます。システムは各エントリをその日時に描画し、ポリシーに従って新しいタイムラインを要求します。

import WidgetKit
func getTimeline(
    in context: Context,
    completion: @escaping (Timeline<WeatherEntry>) -> Void) {
    let entries = buildEntries()
    let timeline = Timeline(
        entries: entries, policy: .atEnd)
    completion(timeline)
}

更新ポリシー

再読み込みポリシーは、WidgetKitが次のタイムラインを要求する時期を制御します。.atEndは最後のエントリの日時の後、.after(date)は指定した時刻、.neverは手動で再読み込みするまで更新しません。システムには更新回数の予算があるため、1秒ごとの更新は期待しないでください。

import WidgetKit
// .atEnd            -> reload after final entry
// .after(someDate)  -> reload at a chosen time
// .never            -> only on manual reloadTimelines
let policy = TimelineReloadPolicy.atEnd
_ = policy

将来のエントリの作成

よくある方法は、次の数時間分を事前に計算しておくことです。これにより、更新のたびにコードを起動しなくてもWidgetを更新できます。現在から将来に向けて一定間隔でエントリを生成し、それぞれにその時点のデータを保持させます。

import WidgetKit
import Foundation
func hourlyEntries() -> [WeatherEntry] {
    var entries: [WeatherEntry] = []
    let now = Date()
    for hour in 0..<6 {
        let date = Calendar.current.date(
            byAdding: .hour, value: hour, to: now)!
        entries.append(WeatherEntry(date: date,
            temperature: 18 + hour, condition: "Sunny"))
    }
    return entries
}

タイムラインでの非同期データ

ネットワークから取得する必要がある場合は、completionを呼び出す前に実行してください。非同期処理をTaskでラップし、データが到着してから完了させます。プロバイダーに許される時間は短いため、高速に処理してください。

import WidgetKit
func getTimeline(
    in context: Context,
    completion: @escaping (Timeline<WeatherEntry>) -> Void) {
    Task {
        let entry = await fetchForecast()
        let timeline = Timeline(
            entries: [entry], policy: .after(
                Date().addingTimeInterval(3600)))
        completion(timeline)
    }
}
func fetchForecast() async -> WeatherEntry {
    WeatherEntry(date: Date(),
        temperature: 21, condition: "Cloudy")
}

重要度と予算

WidgetKitはバッテリーを保護するため、1日に更新できる回数を制限します。頻繁な更新を強制することはできません。1つのタイムラインに複数のエントリを用意し、妥当な再読み込み時刻を選択してください。アプリからreloadTimelinesを使用するのは、重要なデータ変更があった場合だけにします。

import WidgetKit
// The system, not you, decides exact refresh timing.
// Strategy: pre-bake multiple entries + a sensible policy
// + app-driven reloads on real changes.
let budget = "refreshes are budgeted by the OS"
_ = budget

設定可能なWidgetのプロバイダー

AppIntentConfigurationのWidgetでは、代わりにAppIntentTimelineProviderを使用します。このプロバイダーのメソッドにはユーザーが設定したintentが渡されるため、選択された項目(都市やアカウントなど)に応じたデータを取得できます。

import WidgetKit
// AppIntentTimelineProvider adds the configuration:
//   func timeline(for configuration: MyIntent,
//                 in context: Context)
//       async -> Timeline<Entry>
let configurable = "intent-aware provider"
_ = configurable

プロバイダーを組み立てる

完全なプロバイダーは、即座に返すプレースホルダー、プレビューを考慮した高速なスナップショット、適切な再読み込みポリシーを持つ事前作成済みエントリのタイムラインを提供します。これにより、システムの予算内でWidgetを最新の状態に保てます。

import WidgetKit
// 1. placeholder -> instant dummy
// 2. getSnapshot -> sample when isPreview, else current
// 3. getTimeline -> [entries] + .atEnd or .after
let summary = "three methods, one current widget"
_ = summary

確認問題

プレースホルダーメソッドに関する制約を思い出してください。

まとめ

タイムラインプロバイダーについて学びました。

  • placeholderは即座にダミーデータを返し、getSnapshotは1つのエントリを返します(isPreviewの場合はサンプルを使用します)。getTimelineは将来のエントリとポリシーを返します。
  • 再読み込みポリシーは.atEnd、.after(date)、.neverで、実際の更新回数はOSによって制限されます。
  • 複数のエントリを事前に作成し、非同期の取得処理は完了を通知する前に行います。
  • 設定可能なWidgetではAppIntentTimelineProviderを使用します。
無料で開始

AI チューターと学ぶ Swift — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
122
レッスン
409

よくある質問

「タイムラインプロバイダーとスナップショット」レッスンは無料ですか?

はい。「タイムラインプロバイダーとスナップショット」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。

「タイムラインプロバイダーとスナップショット」で何を学びますか?

時間の経過に応じてウィジェットのコンテンツを提供します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Swift Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「タイムラインプロバイダーとスナップショット」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このSwift Academyレッスンでコードを書いて実行できますか?

はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. WidgetKitウィジェットの構築
  2. タイムラインプロバイダーとスナップショット
  3. App Extensionsの概要
  4. App IntentsとShortcuts
← Swift Academyに戻る