RORK LABEN
NATIVE — Rork Max では AR / LiDAR スキャン、Metal を使った 3D、Dynamic Island、Siri Intents、HealthKit、NFC、App Clips、Core ML まで届きますIOS27 — iOS 27 Developer Beta 4 で Siri AI の対象が iPhone 15 Pro / 15 Pro Max・16 シリーズ・17 系へ広がり、応答が初期ベータより明確に速くなりましたDESIGN — iOS・iPadOS・macOS 27 向けの Apple 純正デザインキットが Figma と Sketch 向けに公開されました。新 OS の UI を組む段階で参照できますCANARY — Android 17(Cinnamon Bun)は従来の Developer Preview を廃し、継続更新される Canary ビルドへ移行しました。検証のタイミング設計が変わりますSPARK — Android 17 の Gemini Spark は、アプリを直接操作して配車の予約や注文といった複合的な作業を自動化しますSCALE — Rork は a16z から $2.8M を調達し、月間訪問は74万件規模まで伸びていますNATIVE — Rork Max では AR / LiDAR スキャン、Metal を使った 3D、Dynamic Island、Siri Intents、HealthKit、NFC、App Clips、Core ML まで届きますIOS27 — iOS 27 Developer Beta 4 で Siri AI の対象が iPhone 15 Pro / 15 Pro Max・16 シリーズ・17 系へ広がり、応答が初期ベータより明確に速くなりましたDESIGN — iOS・iPadOS・macOS 27 向けの Apple 純正デザインキットが Figma と Sketch 向けに公開されました。新 OS の UI を組む段階で参照できますCANARY — Android 17(Cinnamon Bun)は従来の Developer Preview を廃し、継続更新される Canary ビルドへ移行しました。検証のタイミング設計が変わりますSPARK — Android 17 の Gemini Spark は、アプリを直接操作して配車の予約や注文といった複合的な作業を自動化しますSCALE — Rork は a16z から $2.8M を調達し、月間訪問は74万件規模まで伸びています
記事一覧/開発ツール
開発ツール/2026-06-17上級

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

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

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

プレミアム記事

個人開発で壁紙系や引き寄せ系のアプリを長く運用していると、「ホーム画面に日替わりで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/月 または ¥1,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駆動開発
※ アフィリエイトリンクを含みます
もっと見る →