RORK LABEN
BUILD — Rork Max はクラウド上の実機 Mac に Xcode と iOS SDK を載せ、SwiftUI を書き、ビルドし、エラーを読んで直す反復を回します。コードを吐いて終わりではない点が生成物の質に効いていますNATIVE — 生成されるのは React Native ではなく純粋な Swift / SwiftUI です。AR や Metal、ウィジェットなど React Native からは届かない機能に手が届くことが、他ビルダーとの実質的な差になりますPLATFORMS — 対応は iPhone・iPad・Apple Watch・Apple TV・Vision Pro に加えて iMessage まで含みます。ウォッチや拡張から入る設計を試すのに向いていますCOMPANION — Rork Companion により、有料の Apple Developer アカウントなしで生成したアプリを実機の iPhone で確認できます。最初の一本を試す段階の障壁が一段下がりましたPRICING — 無料で開始でき有料プランは月額25ドルから、Rork Max は月額200ドルの Max プランです。回収できる本数と規模を先に見積もっておく価値がありますDEADLINE — Google Play は2026年8月31日以降、新規アプリと更新の双方に対象 API レベル36 以上を要求します。残り10日で、生成物の targetSdkVersion は自分で確認が必要ですBUILD — Rork Max はクラウド上の実機 Mac に Xcode と iOS SDK を載せ、SwiftUI を書き、ビルドし、エラーを読んで直す反復を回します。コードを吐いて終わりではない点が生成物の質に効いていますNATIVE — 生成されるのは React Native ではなく純粋な Swift / SwiftUI です。AR や Metal、ウィジェットなど React Native からは届かない機能に手が届くことが、他ビルダーとの実質的な差になりますPLATFORMS — 対応は iPhone・iPad・Apple Watch・Apple TV・Vision Pro に加えて iMessage まで含みます。ウォッチや拡張から入る設計を試すのに向いていますCOMPANION — Rork Companion により、有料の Apple Developer アカウントなしで生成したアプリを実機の iPhone で確認できます。最初の一本を試す段階の障壁が一段下がりましたPRICING — 無料で開始でき有料プランは月額25ドルから、Rork Max は月額200ドルの Max プランです。回収できる本数と規模を先に見積もっておく価値がありますDEADLINE — Google Play は2026年8月31日以降、新規アプリと更新の双方に対象 API レベル36 以上を要求します。残り10日で、生成物の targetSdkVersion は自分で確認が必要です
記事一覧/開発ツール
開発ツール/2026-08-20中級

ベータ SDK でビルドしたアプリは、TestFlight には配れても審査には出せません

ベータ版の Xcode でビルドしたアプリは TestFlight には配布できますが、App Store の審査には提出できません。手元のビルドがどの SDK で作られたかを確認する方法と、eas.json で提出用ビルドを守る設定をまとめました。

Rork539Expo175EAS Build16TestFlight12App Store87

秋の新しい OS の見た目を先に確認したくて、ベータ版の Xcode を入れた月がありました。

壁紙アプリのレイアウトが新しい表示効果でどう崩れるかを見たかっただけです。ビルドは通り、TestFlight にも上がり、テスターの端末にも届きました。ここまでは順調でした。

詰まったのは、その同じビルドをそのまま審査に回そうとしたときです。アップロードは成功しているのに、提出の画面でそのビルドが選べません。

原因はコードではなく、ビルドの中に既に書き込まれていた SDK のバージョンでした。

TestFlight と審査では、受け付ける SDK が違います

先に結論を書きます。Apple はベータ版の SDK でビルドしたアプリを TestFlight の内部・外部テストに配ることを許可していますが、App Store 向けの提出には正式版(Release Candidate 以降)の SDK を求めています。

つまり「アップロードできた=提出できる」ではありません。App Store Connect はアップロードの入口と提出の入口で別々の判定をしていて、ベータ SDK のビルドは前者だけを通過します。

2026年8月20日時点の条件を整理すると、こうなります。

用途 必要な SDK 現時点の例
TestFlight の内部・外部テスト ベータ SDK も可 Xcode 27 beta 5 / iOS 27.0 beta 5 SDK が受付対象
App Store の審査提出 正式版(RC 以降)の SDK ベータ SDK のビルドは提出対象に出てきません
App Store Connect へのアップロード全般 iOS 26 / iPadOS 26 SDK 以上 2026年4月28日から適用

3行目は見落としやすい条件です。「ベータを避ければいい」と考えて古い Xcode に戻すと、今度は最低要件のほうに引っかかります。上にも下にも壁がある、という理解が正確です。

なお iOS 27 SDK の必須化はまだ告知されていません。今すぐ Xcode 27 に上げる必要はない、というのが現時点の判断です。この手の条件は数か月単位で動くため、実際に提出する直前に App Store Connect のリリースノートXcode の SDK 要件 を開いて確認してください。

手元のビルドがどの SDK で作られたかを確認する

「たぶん正式版だったはず」で提出に進むと、審査の直前に足が止まります。確認は数秒で終わるので、習慣にしてしまうのが早いです。

判定材料は .ipa の中の Info.plist に入っています。ビルド時に Xcode が自動で書き込む項目で、後から手で書き換えるものではありません。

#!/usr/bin/env bash
# ipa-sdk.sh — .ipa がどの SDK / Xcode でビルドされたかを表示する
set -euo pipefail
 
IPA="${1:?usage: ipa-sdk.sh <path-to-ipa>}"
 
# .ipa は zip なので、Payload/*.app/Info.plist を展開せずに読み出します
PLIST_PATH="$(unzip -Z1 "$IPA" 'Payload/*.app/Info.plist' | head -1)"
 
unzip -p "$IPA" "$PLIST_PATH" \
  | plutil -convert xml1 -o - - \
  | grep -A1 -E '<key>(DTSDKName|DTXcode|DTPlatformBuild|MinimumOSVersion)</key>' \
  | grep -v -- '--'

実行するとこのような出力になります。

<key>DTPlatformBuild</key>
<string>23A5308c</string>
<key>DTSDKName</key>
<string>iphoneos27.0</string>
<key>DTXcode</key>
<string>2700</string>
<key>MinimumOSVersion</key>
<string>16.0</string>

読み方はこうです。DTSDKName がビルドに使われた SDK、DTXcode が Xcode のバージョン(2700 は 27.0)です。決め手になるのは DTPlatformBuild で、ビルド番号の末尾に小文字が付いているもの(上の例の 23A5308c)はベータ配布のビルドです。正式版になると末尾の小文字が消えます。

unzip -p で標準出力に流してから plutil に渡しているのは、.ipa を丸ごと展開したくないからです。数百 MB のファイルを毎回展開するのは、CI でも手元でも無駄が大きくなります。バイナリ形式の plist をそのまま grep しても読めないため、plutil -convert xml1 -o - を挟んでいます。

Xcode を選んでいるのは、Rork ではなく eas.json です

Rork でエクスポートしたプロジェクトを EAS Build に載せている場合、どの Xcode が使われるかは eas.jsonimage が決めています。ここを一度も触っていないなら、既定の auto が効いています。

image に指定できる値には別名(エイリアス)があり、意味がそれぞれ違います。

指定 意味 提出用ビルドでの扱い
auto(未指定時の既定) その Expo SDK に見合ったイメージを EAS が選ぶ 基本はこれで問題ありません
latest 最後に追加されたイメージを指す ベータ Xcode のイメージが追加されると自動で追随します
sdk-57 のような SDK 別名 特定の Expo SDK 向けのイメージ 意図が読めるので、固定したいときに向きます

注意したいのは latest です。名前から「安定版の最新」を想像しがちですが、実際には「直近で追加されたイメージ」であり、ベータ Xcode のイメージが公開された時点でそちらを指しにいきます。設定した本人が忘れた頃に、提出用ビルドがベータ SDK で作られる、という順序で起こります。

私が個人開発で使っている形は、提出用とベータ確認用を最初から分けておくやり方です。

{
  "build": {
    "production": {
      "distribution": "store",
      "ios": {
        "image": "sdk-57"
      }
    },
    "beta-preview": {
      "distribution": "internal",
      "channel": "beta-preview",
      "ios": {
        "image": "latest"
      }
    }
  }
}

production を SDK 別名で固定しておけば、新しいベータのイメージが追加されても提出用ビルドは動きません。新しい OS の見た目を確かめたいときは eas build --profile beta-preview を使い、こちらは内部配布に閉じておきます。

分けておく利点は、うっかりを防げることだけではありません。「今日のビルドはどちらの枠で作ったか」がプロファイル名で残るため、後から履歴を追うときに迷いません。

実際に使われた Xcode は、ビルドログの先頭付近に出るイメージ名で確認できます。設定した値と一致しているかを、最初の1回だけでも見ておくと安心です。

提出の直前に落とす仕組みを1つ入れておく

人の注意力に任せる部分は、いずれ抜けます。私は提出前の確認を1コマンドにまとめて、条件を満たさなければその場で止まるようにしています。

#!/usr/bin/env bash
# guard-release-sdk.sh — ベータ SDK のビルドを提出フローの手前で止める
set -euo pipefail
 
IPA="${1:?usage: guard-release-sdk.sh <path-to-ipa>}"
 
PLIST_PATH="$(unzip -Z1 "$IPA" 'Payload/*.app/Info.plist' | head -1)"
XML="$(unzip -p "$IPA" "$PLIST_PATH" | plutil -convert xml1 -o - -)"
 
read_key() {
  echo "$XML" | grep -A1 "<key>$1</key>" | tail -1 | sed -E 's/.*<string>(.*)<\/string>.*/\1/'
}
 
SDK_NAME="$(read_key DTSDKName)"
PLATFORM_BUILD="$(read_key DTPlatformBuild)"
 
echo "SDK: ${SDK_NAME} / platform build: ${PLATFORM_BUILD}"
 
# ベータ配布のビルド番号は末尾に小文字が付きます(例: 23A5308c)
if [[ "$PLATFORM_BUILD" =~ [a-z]$ ]]; then
  echo "審査には出せないビルドです。正式版 SDK で作り直してください。" >&2
  exit 1
fi
 
echo "提出可能な SDK でビルドされています。"

判定を DTPlatformBuild の末尾1文字に置いているのは、SDK 名だけでは足りないからです。iphoneos27.0 という文字列は、ベータでも正式版でも同じ値になります。ベータかどうかを分けているのはプラットフォームのビルド番号のほうです。

このスクリプトを提出前の手順の先頭に置いておくと、判断が「思い出す」から「実行する」に変わります。個人でリリースを回していると、確認の工程ほど省略の対象になりやすいので、止まる仕組みのほうを用意しておくのが現実的だと感じています。

TestFlight まで届いたのに公開後に挙動が変わる場合は、SDK ではなくビルド構成側の問題であることが多いです。その切り分けはTestFlight は問題ないのに App Store 公開後にクラッシュする4つの理由にまとめています。

今日のうちに見ておく場所

eas.json を開いて、提出用プロファイルの ios.imagelatest になっていないかを確認してください。ここが latest のままなら、次にベータのイメージが追加された日に、提出できないビルドが静かに作られます。

一行の設定ですが、秋の OS 更新期に効いてくる場所です。私自身、上の一件があってから提出用の枠だけは固定するようになりました。

お読みいただきありがとうございました。同じところで足を止める方が一人でも減れば嬉しいです。

シェア

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

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

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

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

関連記事

開発ツール2026-03-21
Rork × GitHub Actions で CI/CD を構築する — EAS Build 自動化からテストフライト配布まで
Rork で作ったアプリに GitHub Actions と EAS Build を使った CI/CD パイプラインを構築する方法を解説。プルリクエストごとの自動テスト、ビルド自動化、TestFlight への自動配布までを実践的にカバーします。
開発ツール2026-08-14
ライセンス表示に載せる依存は、lockfile の dev/prod では決まりません
AI ビルダーが書き出したプロジェクトの依存を実際に分類し、ライセンス表示に載せる範囲をどう決めたかの記録です。copyleft の検出結果と配布物の境界の食い違いを、本番プロジェクトの実データで確かめました。
開発ツール2026-07-17
Rork の App Store 提出が「輸出コンプライアンス」で毎回止まるのを設定1行で終わらせる
Rork と Rork Max のビルドを App Store Connect に上げるたびに出る Missing Compliance 警告。免除の判断基準と、app.json / Info.plist で恒久的に消す設定、消えない場合の原因を整理しました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →