RORK LABEN
SDK58 — Expo SDK 58 のベータが始まりました。React Native 0.88 の RC を同梱し、ベータ期間は3〜4週間と公式に書かれています11/01 — Google Play の対象 API レベル、延長を申請した場合の配信期限は11月1日です。残り44日ですEASENV — ローカルビルドに渡したはずの秘密が、中身ではなく変数名の文字列のまま届く、という報告が長く開いたままですNEW — 推奨された移行先が、すでに停止していました。廃止表を74行突き合わせた記録ですUISCENE — iOS 27 では新しい画面ライフサイクルが必須です。SDK 57 では自分で有効にする設定で、既定になるのは 58 からですCREDIT — 「AI のエラーには消費しない」がどこまでを指すのかは、同じ修正を何度か頼んだ日の記録を取ると見えてきますSDK58 — Expo SDK 58 のベータが始まりました。React Native 0.88 の RC を同梱し、ベータ期間は3〜4週間と公式に書かれています11/01 — Google Play の対象 API レベル、延長を申請した場合の配信期限は11月1日です。残り44日ですEASENV — ローカルビルドに渡したはずの秘密が、中身ではなく変数名の文字列のまま届く、という報告が長く開いたままですNEW — 推奨された移行先が、すでに停止していました。廃止表を74行突き合わせた記録ですUISCENE — iOS 27 では新しい画面ライフサイクルが必須です。SDK 57 では自分で有効にする設定で、既定になるのは 58 からですCREDIT — 「AI のエラーには消費しない」がどこまでを指すのかは、同じ修正を何度か頼んだ日の記録を取ると見えてきます
記事一覧/開発ツール
開発ツール/2026-06-17上級

Rork Max のネイティブ Swift ウィジェットで日替わり表示が止まる — TimelineProvider の更新予算を設計する

Rork Max が生成するネイティブ Swift のホーム画面ウィジェットは、TimelineProvider の更新予算を理解しないと日替わり表示が翌日以降に止まります。reloadPolicy と App Group、ディープリンクまでを実アプリ設計の観点で整理します。

Rork Max234WidgetKit11Swift48ホーム画面ウィジェット個人開発212

プレミアム記事

個人開発で壁紙系や引き寄せ系のアプリを長く運用していると、「ホーム画面に日替わりで1枚見せたい」という要望は必ず出てきます。Rork Max がネイティブ Swift でウィジェットを出力できるようになって、私自身も既存アプリに WidgetKit を載せ直してみたのですが、最初のビルドで素直に詰まりました。シミュレータでは日替わりに見えるのに、実機に入れて翌朝確認すると、ウィジェットが前日の1枚のまま固まっていたのです。

原因は、生成された TimelineProvider が「いつ・どれだけ更新を予約するか」を決めていなかったことでした。WidgetKit のタイムラインは cron ではありません。ここを設計せずに Rork Max の出力をそのまま出すと、初日は動いて2日目から止まる、という最もたちの悪い壊れ方をします。

ウィジェットが止まるのは「予算」を使い切るから

WidgetKit はバッテリーを守るため、各ウィジェットが受け取れる更新回数に1日あたりの上限(更新予算)を設けています。Apple の公開ガイダンスでは、ホーム画面に置かれ頻繁に閲覧されるウィジェットでおおむね 1日40〜70回 が目安とされ、TimelineProvider が返したタイムラインのエントリ消化や reloadTimelines(ofKind:) の呼び出しはこの予算から差し引かれます。

ここで重要なのは、タイムラインの最後のエントリを過ぎても、次のタイムラインの再生成は自動では走らないという点です。getTimeline で「今日の0時のエントリ1件だけ」を返し、reloadPolicy を指定しなかった場合、システムは「いつ次を読み込むべきか」を知りません。結果として、表示は最後のエントリのまま固定されます。ここが最大の落とし穴です。シミュレータで気づけないのは、デバッグ実行のたびにタイムラインが再生成されるためで、本番運用の挙動とは別物です。

予算は「使い切ったら次の日まで回復しない」性質があるので、設計の目標は2つになります。第一に、1日の更新回数を予算内に収めること。第二に、その範囲で確実に翌日分へ繋ぐこと。日替わり表示なら、本当に必要な更新は1日1回です。予算を気にして過剰に減らすより、reloadPolicy を正しく使って「次の更新時刻」を明示するほうが安全です。

reloadPolicy で「次にいつ起こすか」を必ず宣言する

Timeline(entries:policy:)policy には3種類があります。.atEnd は最後のエントリを過ぎたら再読み込み、.after(date) は指定時刻に再読み込み、.never は再読み込みしないという意味です。日替わりウィジェットでは、翌日0時を明示する .after が最も予測可能です。

import WidgetKit
import SwiftUI
 
struct DailyEntry: TimelineEntry {
    let date: Date
    let title: String
    let imageName: String
}
 
struct DailyProvider: TimelineProvider {
    func placeholder(in context: Context) -> DailyEntry {
        DailyEntry(date: Date(), title: "今日の一枚", imageName: "placeholder")
    }
 
    func getSnapshot(in context: Context, completion: @escaping (DailyEntry) -> Void) {
        completion(currentEntry())
    }
 
    func getTimeline(in context: Context, completion: @escaping (Timeline<DailyEntry>) -> Void) {
        let entry = currentEntry()
 
        // 翌日0時(端末ローカル)を次の更新時刻として明示する
        let calendar = Calendar.current
        let startOfTomorrow = calendar.startOfDay(
            for: calendar.date(byAdding: .day, value: 1, to: entry.date)!
        )
 
        let timeline = Timeline(entries: [entry], policy: .after(startOfTomorrow))
        completion(timeline)
    }
}

ここでの肝は、エントリを「今日の1件」に絞り、reloadPolicy.after(翌日0時) にしている点です。こうすると、システムは翌日0時前後にもう一度 getTimeline を呼び、そこで「次の日の1枚」が確定します。1日の更新は実質1回で済み、予算の枯渇を回避できます。

.atEnd でも動きますが、エントリを1件しか積んでいないと「最後のエントリ=今表示中」になり、再読み込みのタイミングが曖昧になります。確実に日付の境界で切り替えたいなら、.after で時刻を握るほうが意図どおりに動きます。私自身は、.atEnd で組んだ初回ビルドが翌日に固まり、.after に変えて解消した経緯があるので、日替わり用途では .after を既定にしています。個人的にも、日替わり表示ではこの方針を推奨します。注意点として、.after の時刻は端末ローカルの0時に合わせるのが無難です。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
TimelineProvider の reloadPolicy と日次更新予算を踏まえ、日替わりウィジェットを翌日以降も止めずに回す設計
App Group 経由でアプリ本体とウィジェットがコンテンツを共有し、ネットワークなしで当日分を確定させる実装パターン
ウィジェットのタップを Widget URL で該当画面へ正しく繋ぐディープリンク設計と、よくある失敗の切り分け
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

関連記事

開発ツール2026-07-18
AR で置いたものが翌朝には消えている — ARWorldMap による配置の永続化とリローカライズ設計
Rork Max が生成する AR アプリは、置いた 3D オブジェクトがアプリ再起動で消えます。ARWorldMap の保存タイミング、カスタムアンカーの符号化、リローカライズ待ちの見せ方、成立しない時の逃げ道までを設計として整理しました。
開発ツール2026-07-16
Rork Max 生成コードの再生成ゾーン設計 — 手を入れるほど失われる「作り直せる自由」を残す
Rork Maxの生成コードに乗っている「捨てて作り直せる」という見えない資産は、手を入れるたびに静かに失われます。再生成ゾーンの残し方、境界に置く型の決め方、台帳とCI検査によるドリフト検出、四半期ごとの再生成テストまで、個人開発の実運用からまとめます。
開発ツール2026-07-13
HealthKitの差分同期でデータを取りこぼす — HKAnchoredObjectQueryのアンカーを設計する
HealthKitの差分同期で歩数や睡眠が二重に数えられたり欠けたりする原因は、HKQueryAnchorの永続化設計にあります。newAnchorとdeletedObjectsを正しく扱い、再インストールやバックグラウンド更新をまたいでも整合するローカル取り込みの実装を、動くSwiftコードでまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます