コマンドラインから iOS の Simulator を起動して、アプリをインストールしたいことがあったので、その方法を調査した内容を記事にしました。
調査時の環境
- Xcode 16.3
- macOS 15.4.1
方法
単純に Simulator をコマンドラインから Simulator を起動して、アプリをインストールしたいだけならちょっと調べてたら、たくさん記事が出てきましたので、以下を参考にさせていただきました。
方法は簡単で、以下手順で行えます。
1. アプリをビルド
まずはxcodebuild
コマンドで、インストールしたいアプリをビルドします。
ポイントは、-derivedDataPath
で DerivedData の生成先を指定するところです。
アプリインストールを実行するときに、DerivedData の中からアプリの実行可能ファイルを使うので、DerivedData の場所がわかるように、あらかじめ指定しておきます。
コマンド例
xcodebuild \
-projec hoge.xcprojc \
-scheme hoge \
-configuration Debug \
-destination "platform=iOS Simulator,OS=18.1,name=iPhone 16 Pro" \
-derivedDataPath <ビルドの成果物の格納先のパス>
build
目的はDerivedDataを生成することなので、xcodebuild
にこだわる必要はなしです。
fastlane
のscan
でも同じことができるはずですので、xcodebuild
コマンドを使った方法はあくまで一例です。
2. Simulator の起動
続いて、xcrun simctl
コマンドで Simulator を起動します。
コマンド例
xcrun simctl boot <デバイス名 or SimulatorのUDID>
ビルドと Simulator の起動は順番が前後しても問題ありません。
Simulator はコマンド実行完了後も Simulator がすぐ使える状態ではないこともあるので、ビルドも前に実行しておく方が全体の実行時間は下がりそうです。
特に事情がなければさきに Simulator の起動を実行しておいた方が良いでしょう。
3. Simulator にアプリをインストール
最後にxcrun simctl
コマンドで Simulator へアプリをインストールします。
コマンド例
- 複数の Simulator が起動していて、特定のデバイスにインストールしたい場合
xcrun simctl install <デバイス名 or SimulatorのUDID> <DerivedDataのパス/Build/Products/Debug-iphonesimulator/hoge.app>
- 起動している Simulator のどれかにアプリをインストールする
xcrun simctl install booted <DerivedDataのパス/Build/Products/Debug-iphonesimulator/hoge.app>
booted
を指定すると、起動している Simulator を自動で選択してくれます。
CI 環境などで Simulator がひとつしか起動していないことがわかっている場合も、booted
を指定した方が簡潔で良さそうです。
以下 simctl コマンドの help コマンドの説明を引用
For subcommands that require a argument, you may specify a device UDID
or the special "booted" string which will cause simctl to pick a booted device.
If multiple devices are booted when the "booted" device is selected, simctl
will choose one of them.
起動したい Simulator のバージョンを指定したいときはどうする?
私のユースケースとして、Github Actions の CI 環境で決まった Simulator に対して Maestro を使って E2E テストを行うというものだったため、アプリインストール済みの Simulator を事前に起動しておきたかったです。
E2E テスト内でスクリーンショットも撮ったりするので前提として、実行する Simulator の種類、iOS バージョンは固定しておきたかったです。
xcrun simctl boot
コマンドで Simulator を起動するときに、バージョンまで指定したい場合は、UDID による指定しかなさそうでした。
ただ、Github Actions の macOS ランナーでは Simulator の UDID が変わってしまうことがあるので、固定で UDID を指定すると UDID が変わったときにワークフローが壊れてしまう懸念もありました。
そこで、xcrun simctl list
で Simulator のデバイス名、バージョン、UDID を一覧出力して、そこから指定のデバイスの UDID を動的に取得する方法で対応することにしました。
そうすれば、Simulator の UDID が勝手に変わろうとも、動的に取得するのでワークフローが壊れることはありません。
以下のようなスクリプトを作成し、指定したデバイス名、バージョンの合致する Simulator を起動するようにしました。
#!/bin/bash
DEVICE_NAME="$1"
IOS_VERSION="$2"
if [ -z "$DEVICE_NAME" ] || [ -z "$IOS_VERSION" ]; then
echo "Usage: $0 \"<Device Name>\" \"<iOS Version>\""
exit 1
fi
# フラグ用変数
FOUND_SECTION=0
UDID=""
# 1行ずつ読み取り
while IFS= read -r line; do
# セクション(-- iOS XX --)の検出
if echo "$line" | grep -q -- "-- $IOS_VERSION --"; then
FOUND_SECTION=1
continue
fi
# 他のバージョンのセクションに入ったら終了
if echo "$line" | grep -q -- "^-- iOS " && ! echo "$line" | grep -q -- "$IOS_VERSION"; then
if [ "$FOUND_SECTION" -eq 1 ]; then
break
fi
fi
# セクション内でデバイス名を探す
if [ "$FOUND_SECTION" -eq 1 ]; then
if echo "$line" | grep -q "$DEVICE_NAME"; then
UDID=$(echo "$line" | grep -oE '[A-F0-9\-]{36}')
break
fi
fi
done < <(xcrun simctl list devices available)
# UDIDが見つかったかチェック
if [ -z "$UDID" ]; then
echo "No matching device found for \"$DEVICE_NAME\" on $IOS_VERSION"
exit 1
fi
echo "Found UDID: $UDID"
# 起動
xcrun simctl boot "$UDID"
echo "Simulator booted successfully."
以下のように使用すれば、指定したデバイスが起動できるようになります。
bash boot_simulator.sh "iPhone 16 Pro" "iOS 18.1"
おわり
以上が、コマンドラインから Simulator へアプリをインストールする方法でした。
xcrun simctl boot
でもバージョン指定できるものと思っていましたが、いくら調べてもなさそうだったので、一手間加えなきゃでしたが、実行方法さえ思いつけば ChatGPT などが簡単にスクリプトを組んでくれるので、便利な世の中になったなーと思いました!