RORK LABEN
MAX — Rork MaxはiPhone・iPad・Apple Watch・Apple TV・Vision Pro向けにネイティブSwiftを生成し、2クリックでApp Store公開でき、Xcodeを必要としませんSTACK — 通常のRorkはReact Native(Expo)でクロスプラットフォームのモバイルアプリを作る位置づけ。用途に応じた使い分けが鍵ですFOCUS — BoltやLovableのようなWeb中心ツールと違い、RorkはiOS/Androidのネイティブアプリ生成に特化していますBUGS — 実利用レビューでは遭遇したバグの約70%を手動介入なしで解決、残り3割はエクスポート済みコードでの手修正が必要と報告されていますFUNDING — Rorkはa16z(Andreessen Horowitz)から$2.8Mを調達しましたPRICING — 無料で開始でき、有料プランは$25/月からです。まず触ってから判断できますMAX — Rork MaxはiPhone・iPad・Apple Watch・Apple TV・Vision Pro向けにネイティブSwiftを生成し、2クリックでApp Store公開でき、Xcodeを必要としませんSTACK — 通常のRorkはReact Native(Expo)でクロスプラットフォームのモバイルアプリを作る位置づけ。用途に応じた使い分けが鍵ですFOCUS — BoltやLovableのようなWeb中心ツールと違い、RorkはiOS/Androidのネイティブアプリ生成に特化していますBUGS — 実利用レビューでは遭遇したバグの約70%を手動介入なしで解決、残り3割はエクスポート済みコードでの手修正が必要と報告されていますFUNDING — Rorkはa16z(Andreessen Horowitz)から$2.8Mを調達しましたPRICING — 無料で開始でき、有料プランは$25/月からです。まず触ってから判断できます
記事一覧/開発ツール
開発ツール/2026-06-17上級

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

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

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

プレミアム記事

個人開発で壁紙系や引き寄せ系のアプリを長く運用していると、「ホーム画面に日替わりで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-04-05
Rork Max × WidgetKit・ライブアクティビティ実装ガイド 2026 — Dynamic Island 対応まで
Rork Max で iOS Widget・ロック画面ウィジェット・Dynamic Island 対応のライブアクティビティを実装する完全ガイド。WidgetKit の基礎から Timeline 更新戦略、App Intents 連携、収益化まで体系的に解説します。
開発ツール2026-06-16
Rork Max のネイティブアプリの中身を iPhone の検索に載せる — Core Spotlight で「探されるアプリ」にする実装
Rork Max が生成するネイティブ Swift アプリのコンテンツを Core Spotlight に索引し、iPhone の検索からアプリ内の特定画面へ直接たどり着ける導線を実装します。索引の登録・更新・削除と、検索結果が古くなる本番の落とし穴を個人開発目線で整理しました。
開発ツール2026-06-16
Rork Max のネイティブアプリで CloudKit 同期を設計する — 競合と削除をどう扱うか
iPhone と iPad で同じデータを同期させたい——Rork Max が生成した Swift アプリに CloudKit を入れる際、本当に難しいのは保存ではなく『競合』と『削除』の扱いでした。実装で固めた設計判断を整理します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →