
Xcodeの旧バージョンを入れる方法。xcodesが2段階認証で止まったら.xipを--pathで渡す
現場のCIに合わせてXcode 26.3が必要になったが、App Storeには最新の27.1しかない。xcodesは2段階認証の6桁で止まった。ブラウザでサインインして.xipを落とし、xcodes install --pathで渡して入れるまでを、実際の画面と出力で載せる。
目次
現場のCIに合わせてXcode 26.3が必要になったが、App Storeには最新の27.1しかない。xcodesは2段階認証の6桁で止まった。ブラウザでサインインして.xipを落とし、xcodes install --pathで渡して入れるまでを、実際の画面と出力で載せる。
個人開発では、App Store から入れた最新の Xcode 27 系を使っています。ところが参画している現場の iOS アプリは、CI(変更のたびに自動でビルドする仕組み)が Xcode 26.3 で動いていて、手元も同じ版に揃える必要が出てきました。
旧版の Xcode は App Store には置かれていません。Apple のサイトから落とすか、版を指定して入れられる xcodes というコマンドを使うのが定番です。どちらも Apple アカウントへのサインインと2段階認証(パスワードのあとに6桁の確認コードを求める仕組み)が要ります。
私は10年近く前に iPhone から Android へ乗り換え、そのときのキャリアメールも放置したままでした。xcodes は6桁のコードを求めたところで止まり、コードはどこにも届きませんでした。最終的には、ブラウザでサインインして Xcode の .xip を自分で落とし、xcodes install 26.3 --path <xip> で渡すことで、コマンド側のサインインなしに入りました。
この記事は、最新の Xcode を入れる普通の手順から始めて、旧版が要る理由、2段階認証で止まったところ、ブラウザ経由で抜けた手順までを、実際の画面と出力で順に載せます。環境は Apple silicon の MacBook Air、macOS 26.6.2 です。
最新の Xcode は App Store から入れる
Mac には、Xcode 本体を入れなくても Command Line Tools(git やコンパイラなど、端末で使う最小限の開発道具)が入っていることがあります。ただし iOS アプリのビルドに使う xcodebuild は、Command Line Tools だけでは動きません。

最新版を入れるなら App Store が一番手軽です。端末で済ませたい場合は、App Store を操作するコマンド mas(Homebrew で入ります)が使えます。Xcode の App Store での番号は 497799835 です。

入れてから使える状態にするまでは、次の4つです。mas get は手元では sudo を求められました。
# App Store から Xcode を入れる
sudo mas get 497799835
# 使う Xcode をこれに切り替える
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
# 初回起動時の追加部品を入れる
xcodebuild -runFirstLaunch
# iOS シミュレーターを入れる
xcodebuild -downloadPlatform iOSこの手順で、Xcode 27.1 と iOS 27.0・27.1 のシミュレーターが入りました(合わせて約15GB)。個人開発ならここで終わりです。
現場の CI は 26.3 だった
現場のアプリを Xcode 27.1 でビルドすると、失敗しました。Swift 6 の並行処理の検査(複数の処理が同じデータを同時に触らないかを、コンパイル時に調べる仕組み)が厳しくなり、それまで通っていた書き方がエラーになったためです(型の名前は置き換えています)。
Testing failed:
Conformance of 'ArrowHead' to protocol 'Shape' crosses into main actor-isolated code and can cause data races
Conformance of 'BubbleTail' to protocol 'Shape' crosses into main actor-isolated code and can cause data races
Testing cancelled because the build failed.
** TEST FAILED **では CI はどの版で動いているのか。GitHub Actions の設定は、Xcode を切り替える setup-xcode に「最新の安定版」を指定していました。
runs-on: macos-15
...
- uses: maxim-lobanov/setup-xcode@v1.7.0
with:
xcode-version: 'latest-stable'直近のリリース用の実行ログを見ると、実際に選ばれていたのは 26.3 でした。
Image: macos-15-arm64
Switching Xcode to version 'latest-stable'...
Xcode 26.3setup-xcode は、GitHub が用意した実行環境(ここでは macos-15)に最初から入っている Xcode の中から選ぶだけで、新しい版を入れはしません(README に "switch between pre-installed versions of Xcode" とあります)。そのため「最新の安定版」の指定でも、App Store の最新(27.1)ではなく、その実行環境で一番新しい 26.3 になります。手元は CI に合わせて 26.3 を入れることにしました。
揃えるのは Xcode だけではありません。コードの書式を整える SwiftFormat も、Homebrew の最新版で走らせると、変更していないのに大量の書き換えが出ました。版を順に試し、現場のコードと一致する版を使うことにしています。
| SwiftFormat の版 | 書き換えが必要と言われたファイル(全603) |
|---|---|
| 0.64.1(Homebrew の最新) | 131 |
| 0.64.0 | 126 |
| 0.63.1・0.63.0 | 120 |
| 0.62.1・0.62.0 | 115 |
| 0.61.1・0.60.1 | 0 |
コードの書き方を検査する SwiftLint も、0.65.1 では違反が8件出て、0.65.0 では現場の状態と一致しました。
旧版は App Store に無い
App Store で入るのは最新の1本だけです。旧版は Apple の開発者向けダウンロードページに置かれています。Apple の Xcode Resources には、旧版を見るには Apple アカウントでサインインすればよく、有料の Apple Developer Program への加入は要らない、と書かれています。
端末から入れるなら xcodes が便利です。版を並べて入れておき、切り替えられます。xcodes list で、入れられる版が一覧になります。

入れ方は3通りあり、違いは Apple アカウントのサインインをどこで通すかです。今回は真ん中の道で止まり、一番下の道で抜けました。

なお、Xcode を切り替えると Mac 全体の設定が変わり(sudo が要ります)、1本で十数GBを使います。版をいくつも並べるのはやめ、手元には 26.3 の1本だけを置くことにしました。App Store 版は自動で新しい版に上がってしまうので、あとで消します。
xcodes は「6桁」で止まった
xcodes install 26.3 を実行すると、Apple アカウントのパスワードまでは通り、次の表示で止まりました。
Apple ID Password:
Two-factor authentication is enabled for this account.
Enter "sms" without quotes to exit this prompt and choose a phone number to send an SMS security code to.
Enter the 6 digit code from one of your trusted devices:「信頼済みデバイス(そのアカウントでサインイン済みで、確認コードが表示される Apple 製品)から6桁を入れて」という意味です。私の手元にある Apple 製品はこの Mac だけで、Mac は個人の Apple アカウントで iCloud にサインインしていました。それでも、待っても Mac に通知は出ませんでした。システム設定のアカウントの画面にも、コードを自分で表示する項目は見当たりませんでした。
表示にあるとおり sms と打てば電話番号へ送る道もありますが、アカウントに登録した番号で今も受け取れることが前提です。
xcodes の 2.x 系はサインインの仕組みを作り替えており、2段階認証まわりの不具合の報告が続いています(例: issue #480)。手元は 2.1.0 でした。今回の「通知が来ない」が同じ原因かは確かめていません。
ブラウザなら、同じ Mac に確認が届いた
同じ個人のアカウントで、ブラウザから developer.apple.com にサインインしてみると、こちらは通りました。以下は記事用にあとから同じ流れを撮り直したもので、Apple アカウントのサインイン画面(account.apple.com)を使っています。

パスワードを入れると、2段階認証の画面に「MacBook Air へ送信された確認コード」と出ます。届け先は、いまブラウザを開いているこの Mac 自身です。

直後に Mac 本体へ、どこからのサインインかを地図で示す確認が出ました。xcodes のときには一度も出なかったものです。

「許可する」を押すと6桁のコードが表示されるので、ブラウザの入力欄へ入れればサインインが終わります。

ちなみに、現場の開発用の Apple アカウントで同じようにサインインしたときは、登録してある Android のスマホに SMS で6桁が届きました。コードの届け先はアカウントごとに違います。
ここで混乱しやすいのが、Apple アカウントの使い道が3つあることです。Mac 本体のサインイン、Xcode のダウンロード、Xcode の中でアプリに署名するためのアカウントは、別々のアカウントで構いません。ダウンロードは個人のアカウントで済ませ、現場の開発用アカウントはあとから Xcode の設定に足せば足ります。

.xip を落として署名を確かめる
サインインできたら、ダウンロードページで版を検索します。URL に検索語を付けて https://developer.apple.com/download/all/?q=Xcode%2026.3 を開くと早いです。Apple silicon の Mac なら「Apple silicon」の方を選びます(2.11GB)。「Universal」は Intel の Mac 用、またはほかの人と共有する場合の版です。

落としたファイルは、入れる前に Apple の署名が付いているかを pkgutil --check-signature で確かめます。「signed Apple Software」と出て、証明書が「Apple Root CA」までつながっていれば、Apple が配ったものです。
$ pkgutil --check-signature ~/Downloads/Xcode_26.3_Apple_silicon.xip
Package "Xcode_26.3_Apple_silicon.xip":
Status: signed Apple Software
Certificate Chain:
1. Software Update
Expires: 2029-04-14 21:28:23 +0000
2. Apple Software Update Certification Authority
Expires: 2031-10-15 00:00:00 +0000
3. Apple Root CA
Expires: 2035-02-09 21:40:36 +0000(実際の出力には各証明書の SHA256 フィンガープリントも並びます。ここでは省きました。)
xcodes に --path で渡す
xcodes には、手元の .xip を渡す --path があります。ファイルを自分で用意しているので、xcodes は Apple へサインインしに行きません。実際、パスワードも6桁も聞かれずに進みました。

実行したのは次のとおりです。最後の sudo rm -rf /Applications/Xcode.app は、先に入れた App Store 版(27.1)を消すためです。App Store 版も残したい人は、この行を外してください。
# 入れて、使う版に選び、展開を速め、終わったら .xip を完全に消す
xcodes install 26.3 \
--path ~/Downloads/Xcode_26.3_Apple_silicon.xip \
--select --experimental-unxip --empty-trash
# 利用規約に同意する
sudo xcodebuild -license accept
# 初回起動時の追加部品を入れる
xcodebuild -runFirstLaunch
# この版に合う iOS シミュレーターを入れる
xcodebuild -downloadPlatform iOS
# App Store 版(27.1)を消す
sudo rm -rf /Applications/Xcode.app
# 入っている版を確かめる
xcodes installed--empty-trash を付けると、入れ終わった .xip はゴミ箱にも残りません。もう一度使う可能性があるなら外しておくと、2GB を落とし直さずに済みます。
27.1 用に入れた iOS 27 のシミュレーターは、xcrun simctl runtime delete で消しました。xcrun simctl runtime list の合計は、iOS 26.3.1・27.0・27.1 の3つで 22.7G だったのが、26.3.1 だけの 7.8G になりました。

あとから版を切り替えたくなったら xcodes select を使います。プロジェクトに .xcode-version というファイルがあれば、引数なしの xcodes select がそこに書かれた版を選びます。
26.3 でビルドとテストが通った
26.3 に替えると、27.1 で失敗したアプリ本体のビルドは通りました。一方でテストのコードは、5か所が 26.3 ではコンパイルできませんでした。Swift Testing の #expect の中で #require を使う書き方です(変数などの名前は置き換えています)。
// 26.3 でエラー: call can throw, but it is executed in a non-throwing autoclosure
try #expect(model.destination == .detail(id: #require(UUID(uuidString: idString))))
// 先に取り出してから比べると通る
let id = try #require(UUID(uuidString: idString))
#expect(model.destination == .detail(id: id))この5か所を書き直すと、テスト1944件がすべて通りました(失敗0件)。新しい Xcode で書いたテストが、古い Xcode ではコンパイルできないことがある、という例です。
手順のおさらい
- 1.CI のログで、実際に使われている Xcode の版を確かめる(「latest-stable」の指定は、App Store の最新とは限らない)
- 2.ブラウザで developer.apple.com/download/all/ にサインインし、その版の .xip を落とす
- 3.
pkgutil --check-signatureで Apple の署名を確かめる - 4.
xcodes install <版> --path <xip> --selectで入れる - 5.SwiftFormat・SwiftLint などの道具も、現場のコードと一致する版に揃える
カバー写真: Wilfredor 撮影・CC0(文字を重ねる加工あり)

Backend Engineer / AWS / Django / Go