◉RORK LABEN
●GPT6.1 — Rork のモデルメニューに GPT-6.1 Sol が加わりました(9月29日)。GPT-6 Sol と同価格で、1M トークンの文脈を読みます●10/12 — React Native 0.88.x の正式リリース予定まで残り6日。Expo SDK 58 安定版はその後で、Expo Go の更新で SDK 57 のサポートが落ちます●CRYPTO — expo-crypto の digest() が、TypeScript 上は ArrayBuffer を受けるのに Android のネイティブ側は TypedArray を求める、という Issue が出ています(修正 PR あり)●NEW — モデルメニューの入れ替わりを3種類に分けて、クレジットの行き先を台帳に残します●SDK58 — SDK 58 の安定版の日付は、昨日の確認時点ではまだ出ていませんでした●SHEET — expo-ui の BottomSheet で presentationBackground の素材が平らで不透明に描かれる、という報告が出ています●GPT6.1 — Rork のモデルメニューに GPT-6.1 Sol が加わりました(9月29日)。GPT-6 Sol と同価格で、1M トークンの文脈を読みます●10/12 — React Native 0.88.x の正式リリース予定まで残り6日。Expo SDK 58 安定版はその後で、Expo Go の更新で SDK 57 のサポートが落ちます●CRYPTO — expo-crypto の digest() が、TypeScript 上は ArrayBuffer を受けるのに Android のネイティブ側は TypedArray を求める、という Issue が出ています(修正 PR あり)●NEW — モデルメニューの入れ替わりを3種類に分けて、クレジットの行き先を台帳に残します●SDK58 — SDK 58 の安定版の日付は、昨日の確認時点ではまだ出ていませんでした●SHEET — expo-ui の BottomSheet で presentationBackground の素材が平らで不透明に描かれる、という報告が出ています
記事一覧/開発ツール
⬡ 開発ツール/2026-08-20中級

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

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

Rork575Expo212EAS Build19TestFlight13App Store89

秋の新しい 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.json の image が決めています。ここを一度も触っていないなら、既定の 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.image が latest になっていないかを確認してください。ここが latest のままなら、次にベータのイメージが追加された日に、提出できないビルドが静かに作られます。

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

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

シェア

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

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

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

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

関連記事

⬡ 開発ツール2026-09-21
exit code 0 で止まるビルド — ログを黙らせていた設定と、空ファイルを通した存在チェック
eas build --local が exit code 0 but produced no further output で止まる件と、0 バイトのスタブが埋め込まれず dyld で落ちる件。どちらも原因は出力を減らす設定でした。自分のスクリプトを棚卸しする手順まで書き残します。
⬡ 開発ツール2026-09-07
.easignore を置くと .gitignore は読まれなくなります — EAS Build に上がるファイルを手元で数える
EAS Build がアップロードする範囲は .gitignore で決まり、.easignore を置いた時点で入れ替わります。同梱ファイルを送信前に数える手順と、親ディレクトリを除外すると感嘆符では戻せないという実測結果をまとめました。
⬡ 開発ツール2026-08-14
ライセンス表示に載せる依存は、lockfile の dev/prod では決まりません
AI ビルダーが書き出したプロジェクトの依存を実際に分類し、ライセンス表示に載せる範囲をどう決めたかの記録です。copyleft の検出結果と配布物の境界の食い違いを、本番プロジェクトの実データで確かめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます