RORK LABEN
TOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しましたTOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しました
記事一覧/開発ツール
開発ツール/2026-05-01上級

Rork のアプリが OS アップデートで突然壊れる前に — 沈黙する非推奨 API を先回りで掴む運用設計

Apple や Google の年次アップデートで動かなくなる前に、非推奨 API・必要な PrivacyInfo・Required Reason API を継続的に監視する運用設計。Rork で長く動かすための実践パターンと自動チェックを紹介します。

rork58ios12android3deprecationmaintenance

私が個人開発で公開しているアプリは、いま 2014 年の最初の一本から数えて 10 年を超えました。10 年動いたアプリも、明日 OS が変われば動かなくなる可能性が常にあります。実際、ある朝メールを開いたら Apple から「あなたのアプリは PrivacyInfo に未申告の Required Reason API を使っています」という通知が届いていて、提出物がリジェクトされたことが何度もありました。「使っていないはず」と思って調べると、依存している小さなライブラリが内部で UserDefaults を呼んでいたり、Expo の Update プラグインが systemUptime を取得していたりするのです。

OS アップデートの怖さは、エラーで気づかせてくれない 「沈黙する非推奨」 にあります。動いているうちは何も言わない API が、ある朝のメールでいきなり「使えなくなります」と言われる。ここでは私が Rork で運用しているアプリ群で実装している「沈黙する非推奨を先回りで掴む」運用設計を、CI スクリプトのレベルまで踏み込んで共有します。

なぜ「沈黙する非推奨」がこれほど厄介なのか

通常のバグであればクラッシュレポートが上がってきます。しかし非推奨化は別の動き方をします。

  • Apple Reject 通知メール は、submit のたびにしか届かない
  • iOS Privacy Manifest 要件 は、新規 API 追加が静かに行われ、3 か月後に強制になる
  • Android targetSdkVersion は、毎年 8 月頃に基準が引き上がり、対応しないと新規アップデートを受け付けない
  • Expo SDK は、メジャーバージョンを跨ぐと依存ネイティブモジュールが互換切れする

これらの共通項は 「あなたのコードはまだ動いている」 ことです。動いているからクラッシュレポートに出ありません。けれど来月のリリースで突然 reject される、あるいは 1 年後にストアから消える、という形で結末がやってきます。

私のチェックリスト運用は、この「沈黙の期間」をなくすことを目的にしています。動いているうちに、それでも見つける仕組み。これがないと、毎年夏の Apple WWDC から秋の iOS リリースまでの 2 か月間、私は仕事ができなくなります(実話です)。

監視すべき 4 つのレイヤー

非推奨は 1 か所では起きません。少なくとも次の 4 か所を継続的に観察する必要があります。

  1. Required Reason API(iOS) — Apple が指定する 100 弱の API リスト。UserDefaultsfileTimestampssystemUptime など。PrivacyInfo.xcprivacy での宣言が必須
  2. Privacy Manifest(依存ライブラリ) — サードパーティ SDK がプライバシーマニフェストを同梱しているか
  3. targetSdkVersion(Android) — Google Play の毎年の最低要件
  4. 依存パッケージの非推奨警告npm ls --silent で出る peer dep 警告、Xcode のビルド警告

それぞれ別のメカニズムで検出する必要があります。1 つのスクリプトで全部見ようとして失敗した経験があるので、いまは観点ごとに別々のチェックを走らせています。

レイヤー 1:Required Reason API の自動検出

Required Reason API は、iOS の PrivacyInfo.xcprivacy で「なぜそれを使うのか」を宣言する必要のある API です。Apple のリストは年に数回拡張されるため、チェックスクリプトもリストを更新する必要があります。

私の運用では、Apple のドキュメントから抽出した API シンボルリストを scripts/required-reason-apis.json として保持し、ipa ビルド成果物の中をシンボル検索しています。

// scripts/check-required-reason-apis.ts
import { execSync } from "node:child_process";
import { readFileSync } from "node:fs";
 
interface ApiEntry {
  symbol: string;
  category: string;  // "UserDefaults" / "FileTimestamp" など
  reasonRequired: boolean;
}
 
const apiList: ApiEntry[] = JSON.parse(
  readFileSync("scripts/required-reason-apis.json", "utf8"),
);
 
const ipa = process.argv[2];
const symbols = execSync(
  `unzip -p "${ipa}" "Payload/*.app/*" | nm - 2>/dev/null || true`,
).toString();
 
const declared = new Set<string>(
  // PrivacyInfo.xcprivacy の解析結果から取り出す(plutil で plist→json 化)
  JSON.parse(
    execSync(
      `plutil -convert json -o - $(unzip -p "${ipa}" "Payload/*.app/PrivacyInfo.xcprivacy" > /tmp/p.xcprivacy && echo /tmp/p.xcprivacy)`,
    ).toString(),
  ).NSPrivacyAccessedAPITypes?.map((x: any) => x.NSPrivacyAccessedAPIType) ?? [],
);
 
const undeclared = apiList.filter(
  (api) => api.reasonRequired && symbols.includes(api.symbol) && !declared.has(api.category),
);
 
if (undeclared.length > 0) {
  console.error("❌ Undeclared Required Reason APIs:");
  for (const api of undeclared) {
    console.error(`  - ${api.symbol} (${api.category})`);
  }
  process.exit(1);
}
console.log("✅ All Required Reason APIs are declared");

このスクリプトを CI(GitHub Actions の Xcode ビルド後ステップ)に組み込みます。新しい依存ライブラリを追加したり、Expo SDK を上げた直後に Required Reason API が増えても、ビルド失敗で検出できます。何より重要なのは、reject される前に CI で止まる こと。Apple の reject メールを夜中に読むのは、人生で何度経験しても慣れません。

レイヤー 2:依存ライブラリの Privacy Manifest 監査

サードパーティ SDK は自分自身の PrivacyInfo.xcprivacy を同梱する必要があります。Apple のガイドラインで「commonly used third-party SDKs」リストに入っているライブラリは特に厳しくチェックされます。

#!/usr/bin/env bash
# scripts/check-third-party-privacy-manifest.sh
set -euo pipefail
 
REQUIRED=$(cat scripts/sdks-requiring-privacy-manifest.txt)
MISSING=()
 
while read -r sdk; do
  PATH_GUESS=$(find ios/Pods -path "*${sdk}*PrivacyInfo.xcprivacy" 2>/dev/null | head -1)
  if [ -z "$PATH_GUESS" ]; then
    MISSING+=("$sdk")
  fi
done <<< "$REQUIRED"
 
if [ ${#MISSING[@]} -gt 0 ]; then
  echo "❌ SDKs missing PrivacyInfo.xcprivacy:"
  printf '  - %s\n' "${MISSING[@]}"
  echo ""
  echo "Action: update these pods to a version that includes the manifest,"
  echo "or replace with a maintained alternative."
  exit 1
fi
echo "✅ All required SDKs include PrivacyInfo.xcprivacy"

このチェックは、pod install のたびに走らせます。古いバージョンの SDK を維持していると、ある日突然 Apple から reject 通知が来ます。CI で先に検出するのが現実的な防衛策です。

レイヤー 3:Android targetSdkVersion の継続監視

Android の Google Play 要件は毎年 8 月に上がります。「2026 年 8 月までに targetSdkVersion 36 にしてください」というメールは、その年の 4 月くらいに最初の警告として届きます。これを取り逃すと、新規アップデートが配信できなくなります。

# .github/workflows/sdk-version-check.yml
name: Check Android targetSdk
on:
  schedule:
    - cron: "0 9 1 * *"   # 毎月 1 日に走らせる
  workflow_dispatch:
 
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Read targetSdkVersion
        id: read
        run: |
          TARGET=$(grep -E "targetSdkVersion\s*=" android/build.gradle | sed -E 's/.*=\s*([0-9]+).*/\1/' | head -1)
          echo "target=$TARGET" >> $GITHUB_OUTPUT
      - name: Compare with Google Play minimum
        run: |
          # Google Play の最新の最低 targetSdk(自プロジェクトで毎年更新)
          REQUIRED=36
          if [ "${{ steps.read.outputs.target }}" -lt "$REQUIRED" ]; then
            echo "❌ targetSdkVersion ${{ steps.read.outputs.target }} is below required $REQUIRED"
            exit 1
          fi
          echo "✅ targetSdk OK (${{ steps.read.outputs.target }} >= $REQUIRED)"

毎月 1 回しか走らせていませんが、それで十分です。Google Play の要件改定は半年以上の予告期間があるため、月次チェックで余裕を持って対応できます。

レイヤー 4:Expo SDK と依存パッケージの非推奨警告を「ノイズ」にしない

Expo SDK のメジャーバージョンを上げると、npm lsexpo-doctor が大量の peer dependency 警告を出します。私が長らく失敗していたのは、全ての警告を同列に扱おうとしたことでした。本気で対応すべき警告と、無視してよい警告が混在しているのに。

そこで定着した運用は、警告を 3 段階に分類するスクリプトです。

// scripts/triage-deprecation-warnings.ts
import { execSync } from "node:child_process";
 
interface Warning {
  pkg: string;
  message: string;
}
 
const raw = execSync("npx expo-doctor --no-color 2>&1 || true").toString();
const warnings: Warning[] = parseExpoDoctorOutput(raw); // 自前のパーサ
 
const SEVERITY: Record<string, "block" | "warn" | "note"> = {
  // Apple/Google の強制要件に関わるもの
  "react-native-firebase": "block",
  "expo-notifications": "block",
  "expo-tracking-transparency": "block",
  // 他の SDK と挙動が連動するもの
  "react-native-async-storage": "warn",
  "react-native-mmkv": "warn",
  // 純粋な機能的警告
  "default": "note",
};
 
const triaged = warnings.map((w) => ({
  ...w,
  severity: SEVERITY[w.pkg] ?? SEVERITY.default,
}));
 
const blocks = triaged.filter((w) => w.severity === "block");
if (blocks.length > 0) {
  console.error("❌ BLOCK warnings — must address before next release:");
  for (const w of blocks) console.error(`  - [${w.pkg}] ${w.message}`);
  process.exit(1);
}
const warns = triaged.filter((w) => w.severity === "warn");
console.log(`⚠ ${warns.length} WARN warnings (non-blocking)`);

「全部赤」のリストは誰も読まなくなります。何を今すぐ直すべきか が一行で分かるリストの方が、結果として対応が進む。これは前回の記事(Claude Code のリリースゲート設計)でも書いた、警告疲れに対する同じ思想です。

通知メールを「タスク」に変換する小さな仕組み

Apple や Google から届く通知メールは、内容が抽象的で対応箇所が分かりづらいことがあります。私の運用では、こうしたメールを Notion の DB に転送し、「症状 / 関係するレイヤー / 対応期限 / 担当者」を必ず埋めるテンプレートを使っています。

件名(メール原文): Submission Failure - PrivacyInfo Missing API Reason
症状: NSPrivacyAccessedAPICategoryUserDefaults が未申告
関係するレイヤー: Layer 1 (Required Reason API)
対応期限: 次回 submit まで
担当者: 自分
最初の一手: scripts/check-required-reason-apis.ts を走らせる

最初の一手 を必ず書く、というのが私の中での唯一のルールです。これがあるかないかで、夜中に通知を読んだときの心理的負荷が大きく違います。何をすればいいか分からない通知は、夜中に読むと精神を削るのです。

「壊れる前に直す」ための年次カレンダー

最後に、私が頭に置いているカレンダーを共有します。OS 周辺の動きには年次のリズムがあるので、そのリズムに合わせて準備するだけで、突発対応がほぼなくなりました。

  • 6 月(WWDC 直後) — iOS 新版の Required Reason API リスト追加を確認、Privacy Manifest 要件の変更を読み込む
  • 7〜8 月 — 新 iOS のベータで Required Reason API スクリプトを実行、reject 候補を洗う
  • 9 月 — iOS 新版リリース時に対応版を submit
  • 4 月 — Google Play の targetSdk 改定通知が来る時期、夏までに対応スケジュールを引く
  • 8 月 — Google Play の targetSdk 強制移行に間に合わせる

この 5 つのチェックポイントを Google Calendar に毎年繰り返しで入れておくだけで、突発リジェクトの 8 割は消えました。残り 2 割は依存ライブラリの予期しない変更ですが、これは Layer 2 と Layer 4 のチェックでだいぶ救えます。

いまから一つだけやるなら

時間がない方のために、いますぐ着手するなら何が効くかを一つだけ。Layer 1 の Required Reason API チェックを CI に組み込むことです。スクリプト本体は半日あれば書けます。Apple の Required Reason API のリストは公開されているので、それを JSON にして symbols を grep するだけ。

私の場合、これを最初に入れた瞬間に、「依存している小さなライブラリが systemUptime を呼んでいた」のを 5 件発見しました。そのうち 2 件は、申告しないまま submit していたら次の reject につながっていたものです。「沈黙する非推奨」を先回りで掴む第一歩としては、これが最も投資対効果の高い一手だと感じています。

シェア

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

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

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

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

開発ツール2026-05-25
Rork で作る iOS アプリに StoreKit 2 で買い切り課金を実装するノート
Rork が生成する Swift / SwiftUI コードに StoreKit 2 で買い切り課金を後付け実装する手順メモ。累計 5,000 万 DL の壁紙アプリで StoreKit 1 から 2 へ移行した経験を踏まえて、ProductID 設計・Transaction 検証・Paywall UI・本番ハマりどころまで実装サンプル込みで共有します。
開発ツール2026-05-20
iOS の 0x8badf00d ウォッチドッグ強制終了に Rork アプリが落ちるときの対処
Rork で作った iOS アプリが起動直後に消える。クラッシュログに 0x8badf00d。Apple のウォッチドッグが React Native の重い初期化を切ったときの正しい直し方を、私の運用中アプリで実際に効いた手順で説明します。
開発ツール2026-05-05
Rork Max で App Store 審査を通すための実践ガイド
Rork Max で作成したアプリが App Store 審査で却下されやすい理由と、審査を通過するための具体的な対処法を解説。メタデータの最適化・プライバシーポリシー・アクセシビリティ・パフォーマンス要件まで実践的にまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →