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-21中級

RorkでビルドしたiOSアプリがTestFlightで「ITMS-90683」拒否される — Info.plistの使用目的文字列の埋め方

Rork書き出しのiOSアプリをApp Store Connectに提出した直後、メールで「ITMS-90683: Missing Purpose String in Info.plist」を受け取る現象について、原因とapp.jsonからの恒久的な修正手順を、12年間の個人開発で繰り返しハマってきた立場から具体的に説明します。

ITMS-90683Info.plist5TestFlight10App Store Connect10iOS108Expo149Rork515プライバシー10トラブルシューティング77

App Store Connect の「Activity」で TestFlight のプロセッシングが終わって安心していたら、数分後に Apple から ITMS-90683: Missing Purpose String in Info.plist という件名のメールが届く。Rork で初めて iOS の submit まで通した人の多くが、ここで一度足を止めることになります。私自身、2014 年から個人で iOS アプリを公開し続けて累計 5,000 万 DL に達した今でも、新しい SDK を入れたタイミングで同じメールを年に数回もらいます。

このエラーは「ビルド失敗」ではないので、ローカルでは気づきにくいのが厄介です。バイナリは無事に App Store Connect に届いていて、内部処理の中で Apple が Info.plist を静的解析した結果として返ってくる、いわば「審査前の自動 reject」に近い扱いになります。Rork で生成したプロジェクト構成を前提に、原因の整理から app.json 経由での修正、そして再 submit までの最短ルートを順番に追っていきます。

ITMS-90683 が出る本当の理由

Apple がこのエラーを返すのは、アプリのバイナリの中で「特定の API を呼ぶコード」が検出されたのに、対応する説明文(Purpose String)が Info.plist に書かれていなかった場合です。Apple のドキュメントでは「Privacy-Sensitive Data API」と呼ばれていて、たとえば次のような領域を触ると説明文が必須になります。

  • 写真ライブラリ・カメラ・マイク
  • 位置情報・モーション・健康データ
  • 連絡先・カレンダー・リマインダー
  • Bluetooth・ローカルネットワーク・FaceID
  • トラッキング(IDFA)・音声認識・Siri

ポイントは、自分が直接 API を呼んでいなくても、依存している SDK が内部で呼び出していれば検出されるという点です。Rork で npx expo install 経由で入れた React Native ライブラリの中には、内部的にカメラやマイクへアクセスする実装を持つものが少なくありません。バナー広告 SDK が IDFA を参照するケースもよくあります。

つまりこのエラーは「あなたのコードが直接触っていないから関係ない」では済まないのです。

まず確認するべきはエラーメールの中身

Apple から届くメールの本文には、欠けている key の名前が必ず列挙されています。たとえばこんな形です。

The app's Info.plist must contain an NSCameraUsageDescription key
with a string value explaining to the user how the app uses this data.

NSCameraUsageDescription の部分が、追加する key 名そのものです。複数列挙されていることもあるので、まずは全部書き写してから次のステップに進んでください。

主な key と、それが要求される代表的なシナリオを表の代わりにリスト化しておきます。

  • NSCameraUsageDescription — 写真撮影、QR コード読み取り、ライブ配信系 SDK
  • NSPhotoLibraryUsageDescription — 写真ライブラリからの選択
  • NSPhotoLibraryAddUsageDescription — 撮影画像をライブラリに保存
  • NSMicrophoneUsageDescription — 音声録音、ビデオ撮影、音声 SDK
  • NSLocationWhenInUseUsageDescription — 位置情報(前景)
  • NSLocationAlwaysAndWhenInUseUsageDescription — 位置情報(背景含む)
  • NSBluetoothAlwaysUsageDescription — BLE 機器との通信
  • NSLocalNetworkUsageDescription — Bonjour 経由のローカル LAN 通信、Chromecast 系
  • NSFaceIDUsageDescription — FaceID による認証
  • NSUserTrackingUsageDescription — IDFA 取得(AdMob、Firebase Analytics などで要求されがち)
  • NSContactsUsageDescription — 連絡先の参照

Rork プロジェクトでの正しい書き方

ここで一番大事なのが、Info.plist を直接編集してはいけないという点です。

Rork は内部で Expo のビルドシステム(EAS Build)を使っており、ビルドのたびに app.json(または app.config.js)から Info.plist を再生成します。Xcode で開いて手動で書き換えても、次のビルドで上書きされて元に戻ります。私もこれで一度 reject を 3 回連続で食らったことがあり、原因が「直すべきファイルが違った」だけだったと気付くまで半日溶かしました。

正しいのは、app.jsonexpo.ios.infoPlist セクションに追記する方法です。AdMob と写真選択機能、それから FaceID ログインを実装したアプリを例にすると、次のようになります。

{
  "expo": {
    "name": "MyRorkApp",
    "ios": {
      "bundleIdentifier": "com.example.myrorkapp",
      "infoPlist": {
        "NSCameraUsageDescription": "QRコードの読み取り時にカメラへのアクセスを使用します。",
        "NSPhotoLibraryUsageDescription": "プロフィール画像を選択するために写真ライブラリへアクセスします。",
        "NSPhotoLibraryAddUsageDescription": "生成した画像を写真ライブラリに保存します。",
        "NSFaceIDUsageDescription": "Face IDで安全にログインするために使用します。",
        "NSUserTrackingUsageDescription": "あなたに合った広告を表示するために、他社アプリやサイトでの行動を関連付けます。"
      }
    }
  }
}

書き込んだら、次の EAS Build から自動で Info.plist に反映されます。Xcode を開いて確認する必要はありませんが、念のため ios/MyRorkApp/Info.plist を grep してキー名が入っているかチェックすると安心です。

文言の品質が後の審査結果に効く

ITMS-90683 をクリアするだけなら、極論「test」と書いても通ります。しかし、ここで適当な文言を入れると、TestFlight は越えられても本審査(App Review)で別途リジェクトされることがあります。私が過去に食らったリジェクト理由には次のようなものがありました。

  • 「カメラへのアクセスをこのアプリで使用」と書いただけで、何のためかが明示されていない
  • 英語版のみで日本語ローカライズが用意されていない
  • 説明文と実際の機能が食い違っている(例: 写真選択しかしないのに「撮影に使用」と書いていた)

文言を考えるときの目安は「ユーザーがアラートを見た瞬間、何のためにこの許可を求められているか即座に理解できるか」です。具体的なユースケースを 1 文で書き、丁寧語で揃えるのが無難です。

ローカライズが必要な場合は、expo-localizationInfoPlist.strings を組み合わせるか、Expo SDK 50 以降であれば app.json 内で expo.locales を指定して言語ごとの文字列を用意できます。

{
  "expo": {
    "locales": {
      "ja": "./languages/ja.json",
      "en": "./languages/en.json"
    }
  }
}

そして languages/ja.json を次のように作っておきます。

{
  "NSCameraUsageDescription": "QRコードの読み取り時にカメラへのアクセスを使用します。",
  "NSPhotoLibraryUsageDescription": "プロフィール画像を選択するために写真ライブラリへアクセスします。"
}

英語版も同じキーで en.json を用意すれば、地域に応じて適切な文言が表示されます。複数言語でリリースする予定があるなら、最初からこの形にしておくと後で楽です。

SDK が暗黙的に要求するケースの見つけ方

問題の半分は「自分が呼んでいない API を SDK が呼んでいる」ことに起因します。エラーメールに NSUserTrackingUsageDescription が含まれているのに自分のコードに requestTrackingAuthorization が一切ないなら、まず疑うのは広告 SDK と分析 SDK です。

私の手元で実際に発生したケースをいくつか挙げます。

  • react-native-google-mobile-ads(AdMob) → NSUserTrackingUsageDescription を要求
  • expo-image-pickerNSPhotoLibraryUsageDescriptionNSCameraUsageDescription
  • expo-cameraNSCameraUsageDescriptionNSMicrophoneUsageDescription(ビデオ撮影機能を持つため)
  • expo-local-authenticationNSFaceIDUsageDescription
  • react-native-zeroconfNSLocalNetworkUsageDescriptionNSBonjourServices
  • @react-native-firebase/analyticsNSUserTrackingUsageDescription(IDFA を取る設定のとき)

どの SDK が何を要求するかは公式ドキュメントで明記されていることもありますが、書かれていないこともあります。一番確実なのは、エラーで指摘された key をそのまま app.json に追加することです。使っていない機能でも、SDK が内部で API を参照している以上、説明文を書く義務が発生します。

修正後の再 submit までの流れ

app.json を更新したら、次の手順で再 submit します。

# 1. ビルドバージョンを上げる(必須)
# app.json の expo.ios.buildNumber をインクリメント
# 例: "1.0.3" → "1.0.4"
 
# 2. EAS Build で再ビルド
eas build --platform ios --profile production
 
# 3. ビルド完了後、submit
eas submit --platform ios --latest

ここでよくあるミスが、buildNumber を上げ忘れて submit して ERROR ITMS-90189: Redundant Binary Upload を食らうパターンです。同じビルド番号は受け付けてもらえません。Rork 経由でビルドしている場合も、生成後に app.json を直接編集してから再ビルドする手順を踏むのが安全です。

submit してから 5〜15 分後に App Store Connect の Activity を確認し、新しいビルドが「Ready to Test」になっていれば成功です。同じ ITMS-90683 が再び返ってきた場合は、メール本文に列挙されている key を全て infoPlist に書ききれているか、もう一度照合してみてください。

予防として組んでおきたいチェックリスト

リジェクトを毎回 submit してから知る、というのは正直しんどいので、私は新しい SDK を入れたタイミングで次の手順を回すようにしています。

  1. npx expo install の直後に、SDK の README で iOS 用 Info.plist 要件を確認する
  2. 要件があれば即 app.jsoninfoPlist に追記する(後回しにすると忘れる)
  3. ローカルで npx expo prebuild --platform ios --clean を実行し、生成された ios/*/Info.plist を grep で確認する
  4. submit 前に eas build の出力ログから Bundle was successfully built を確認する

expo prebuild を一度ローカルで回しておくと、submit 前に Info.plist の中身を目で確認できるのが大きいです。Rork のクラウドビルドだけに依存していると、この中間ファイルを見るタイミングがなくなり、reject されてから気付くサイクルになりがちです。

一歩深いところ — Privacy Manifest との関係

iOS 17 から導入された Privacy Manifest(PrivacyInfo.xcprivacy)は、Info.plist の Purpose String とは別のレイヤーで「データ収集の目的」を申告する仕組みです。ITMS-90683 をクリアしても、Privacy Manifest が不十分だと別の警告(ITMS-91053 など)が返ってきます。

両者の関係を端的に整理すると、Info.plist の Purpose String はユーザーへのアラートに表示される文言、Privacy Manifest は Apple への申告と App Store のプライバシーラベル生成に使われる構造化データです。Rork で React Native の主要 SDK を入れているなら、SDK 側が PrivacyInfo.xcprivacy を同梱しているか確認しておくと、後々の追加リジェクトを避けられます。

ITMS-90683 に出くわすたびに私が思うのは、これは「コードが間違っている」のではなく「ユーザーへの説明が足りていない」というメッセージだということです。短い説明文を 5〜10 個書くだけで、ユーザーがインストール時に得る安心感はかなり変わります。リジェクトメールが届いたら、一手間かけて文言を考える機会だと捉えるのが結果的にいちばん近道です。

同じ場面でつまずいている方の参考になれば幸いです。お読みいただきありがとうございました。

シェア

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

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

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

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

関連記事

開発ツール2026-05-27
Rork で出した iOS アプリの「Missing Compliance」を Info.plist 一行で恒久的に止める
Rork で書き出した iOS アプリを TestFlight に上げるたびに表示される「Missing Compliance」の黄色い警告について、原因と Info.plist への一行追加で毎回の確認作業を消す手順を、6 本の壁紙アプリを並行配信している立場から具体的に書きました。
開発ツール2026-06-29
写真の「選択した項目だけ許可」に正しく向き合う設計
iOS の写真ライブラリ限定アクセス(選択した項目だけ許可)に Rork(Expo)アプリで正しく対応します。フルアクセス・限定・拒否の3状態の判定、選んだ写真だけを扱う前提の画面設計、追加選択を促す導線までを実装コードとともに整理します。
開発ツール2026-06-17
Rorkで書き出したアプリがApp Store Connectで「処理中」のまま止まる — 原因の切り分けと対処
Rorkで書き出したアプリをApp Store Connectにアップロードしたのに、ビルドが「処理中」のまま何時間も止まり、TestFlightにも審査提出にも現れない。私が実際に詰まったときの切り分け手順と、再発を防ぐ事前チェックを実コード付きで整理します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →