◉RORK LABEN
●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…
記事一覧/開発ツール
⬡ 開発ツール/2026-05-27上級

Rork × StoreKit 2 で会員資格の同期を三層化する — 起動時・バックグラウンド・復元購入の役割分担

Rork で生成したアプリに StoreKit 2 のサブスクリプションを組み込むとき、Transaction.updates だけでは届かない領域があります。起動時・Background Refresh・Restore Purchase の三層で状態を回復する具体的な実装と、壁紙アプリ6本で実装してみての所感をまとめました。

Rork585StoreKit 217サブスクリプション66Background RefreshRestore PurchaseiOS115Expo219

✦ プレミアム記事

アーティスト・クリエイターの廣川政樹です。Dolice Labs では Rork で生成した壁紙アプリを 6 本ほど並行運用していて、そのうち 4 本に StoreKit 2 のサブスクリプションを乗せています。Transaction.updates の AsyncStream を一本だけ走らせれば会員資格の同期は終わる、と最初は思っていました。実際にやってみると、ユーザがアプリを長く閉じていたケース・iCloud 同期前にサブスクが切れたケース・端末を移行したケースなど、updates ストリームでは拾えない盲点がいくつもあります。

この記事は、私が個人開発で 2014 年からアプリを作り続けてきて、累計 5,000 万ダウンロードを超えた中で、特にここ 2 年ほどで「会員資格の同期だけは三層構造にしないと取りこぼす」と確信した実装メモです。Rork の生成物に最小差分で乗せられる前提で書いています。

まず一本のアプリで起きた取りこぼし

最初に明確に「これはまずい」と感じたのは、壁紙アプリのうち最も DAU が大きい一本で、サブスク継続率が想定より約 7% 低く出たときでした。Crashlytics には何も上がっておらず、エラーログもきれいです。それでも RevenueCat の Customer Center で個別アカウントを開くと、「サブスクは有効なのにアプリ内では非会員扱い」のセッションが断続的に発生していました。

調査して分かったのは、Transaction.updates を購読しているのは "アプリがフォアグラウンドにいる間" だけだということです。ユーザが土日にアプリを起動せず、その間に更新請求が発生し、月曜にアプリを開いた瞬間に updates イベントは飛んでくる、はずなのですが、@MainActor で囲った購読開始タイミングと、ストアが更新を確定する時刻のミスマッチで、初回 onAppear より遅れて届くケースがありました。会員ユーザに広告が表示され、AdMob の eCPM が想定外に伸びてしまい、課金率の母集団分析を毎月狂わせていました。

この問題は、updates ストリーム一本では構造的に解けません。役割を整理したうえで三層にする必要があります。

なぜ三層化するのか — updates が取りこぼす 3 つの状況

私が運用していて updates が遅延・欠落する状況は、次の 3 つに分類できます。

  1. アプリが完全終了している間に発生した更新請求の確定: iOS は再起動から数秒〜数十秒で updates を補填してきますが、その間に currentEntitlements を読まれると非会員と判定されます。
  2. ネットワーク不調・機内モード解除直後の数十秒: ストアキットは内部リトライを行いますが、エンタイトルメントが回復する前に画面遷移が走ると、UI 側の状態が古いままになります。
  3. 端末移行・iCloud 引き継ぎ後の初回起動: Apple ID は同じでも、レシート同期が完了するまでに数秒〜数分のラグがあり、その間に有料機能を見せようとすると「購入済みなのに使えない」体験になります。

この 3 つに対して、私は次のように層を割り当てています。

取りこぼし状況担当する層
アプリ完全終了中の更新請求第一層: 起動時の currentEntitlements 再評価
ネットワーク不調・バックグラウンド長時間第二層: Background App Refresh による定期照合
端末移行・iCloud 同期遅延第三層: Restore Purchase の手動トリガ

Transaction.updates の購読はあくまで「フォアグラウンドにいる間の即時反映」のための層で、上記 3 つには別の層が必要、という設計です。これを意識しておかないと、updates をいくら丁寧に書いても穴が残ります。

✦

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

この記事の続きを読む

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

この記事で得られること
✦Transaction.updates が取りこぼす 3 つの状況と、それぞれをどの層で回復するかの設計表
✦壁紙アプリ6本の並行運用で実測した、Background Refresh の発火率(24時間あたり 1.8〜3.4 回)と eCPM への影響
✦Restore Purchase をユーザに 1 タップで案内するための UI 配置と、AdMob 月収を約 12% 取り戻したログ分析の手順
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

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

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

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

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

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

関連記事

⬡ 開発ツール2026-04-28
Family Sharing で IAP が消える4つのトリガー — Rork で子ども向けアプリの課金を安全に設計する
Family Sharing 経由の購入で IAP 収益が突然消える原因と、Rork で実装する StoreKit 2・Server Notifications V2 を組み合わせた安全な課金設計を、実コードとテスト手順まで網羅的に解説します。
⬡ 開発ツール2026-09-21
exit code 0 で止まるビルド — ログを黙らせていた設定と、空ファイルを通した存在チェック
eas build --local が exit code 0 but produced no further output で止まる件と、0 バイトのスタブが埋め込まれず dyld で落ちる件。どちらも原因は出力を減らす設定でした。自分のスクリプトを棚卸しする手順まで書き残します。
⬡ 開発ツール2026-09-05
Widget Extension でも BGTaskScheduler.submit は成功します。走らないのは register が親アプリだけのものだからです
Widget Extension から BGTaskScheduler に依頼を出すとビルドも submit も通るのに、翌朝ウィジェットは変わりません。register がホストアプリ専用である事実から、更新の主語を親アプリへ戻す設計まで、壁紙アプリの運用で詰めた手順を残します。