5656
5757ensure_simctl
5858
59+ ensure_core_sim_service () {
60+ local output status
61+ output=" $( xcrun simctl list devices -j 2>&1 ) " || status=$?
62+ if [[ -n " ${status:- } " ]]; then
63+ echo " simctl failed while listing devices (status ${status} ). CoreSimulatorService may be unhealthy." >&2
64+ echo " Try restarting it:" >&2
65+ echo " killall -9 com.apple.CoreSimulatorService 2>/dev/null || true" >&2
66+ echo " launchctl kickstart -k gui/$UID /com.apple.CoreSimulatorService" >&2
67+ echo " Then open Simulator once and rerun devbox run setup-ios." >&2
68+ echo " simctl error output:" >&2
69+ echo " $output " >&2
70+ return 1
71+ fi
72+
73+ if echo " $output " | grep -q " CoreSimulatorService connection became invalid" ; then
74+ echo " CoreSimulatorService is not healthy. Try restarting it:" >&2
75+ echo " killall -9 com.apple.CoreSimulatorService 2>/dev/null || true" >&2
76+ echo " launchctl kickstart -k gui/$UID /com.apple.CoreSimulatorService" >&2
77+ echo " Then open Simulator once and rerun devbox run setup-ios." >&2
78+ echo " simctl error output:" >&2
79+ echo " $output " >&2
80+ return 1
81+ fi
82+ }
83+
5984pick_runtime () {
6085 local preferred=" $1 "
6186 local json choice
@@ -95,6 +120,13 @@ existing_device_udid_any_runtime() {
95120 xcrun simctl list devices -j | jq -r --arg name " $name " ' .devices[]?[]? | select(.name == $name) | .udid' | head -n1
96121}
97122
123+ device_data_dir_exists () {
124+ local udid=" ${1:- } "
125+ [[ -n " $udid " ]] || return 1
126+ local dir=" $HOME /Library/Developer/CoreSimulator/Devices/$udid "
127+ [[ -d " $dir " ]]
128+ }
129+
98130devicetype_id_for_name () {
99131 local name=" $1 "
100132 xcrun simctl list devicetypes -j | jq -r --arg name " $name " ' .devicetypes[] | select((.name|ascii_downcase) == ($name|ascii_downcase)) | .identifier' | head -n1
@@ -105,8 +137,12 @@ ensure_device() {
105137
106138 # If a device with this name already exists anywhere, reuse it.
107139 if existing_udid=$( existing_device_udid_any_runtime " $base_name " ) ; [[ -n " ${existing_udid} " ]]; then
108- echo " Found existing ${base_name} : ${existing_udid} "
109- return 0
140+ if device_data_dir_exists " $existing_udid " ; then
141+ echo " Found existing ${base_name} : ${existing_udid} "
142+ return 0
143+ fi
144+ echo " Existing ${base_name} (${existing_udid} ) is missing its data directory. Deleting stale simulator..."
145+ xcrun simctl delete " $existing_udid " || true
110146 fi
111147
112148 local choice runtime_id runtime_name
@@ -126,8 +162,12 @@ ensure_device() {
126162
127163 # Also check for an existing device with the runtime-qualified display name.
128164 if existing_udid=$( existing_device_udid_any_runtime " $display_name " ) ; [[ -n " ${existing_udid} " ]]; then
129- echo " Found existing ${display_name} : ${existing_udid} "
130- return 0
165+ if device_data_dir_exists " $existing_udid " ; then
166+ echo " Found existing ${display_name} : ${existing_udid} "
167+ return 0
168+ fi
169+ echo " Existing ${display_name} (${existing_udid} ) is missing its data directory. Deleting stale simulator..."
170+ xcrun simctl delete " $existing_udid " || true
131171 fi
132172
133173 echo " Creating ${display_name} ..."
@@ -136,6 +176,7 @@ ensure_device() {
136176}
137177
138178main () {
179+ ensure_core_sim_service || return 1
139180 IFS=' ,' read -r -a devices <<< " ${IOS_DEVICE_NAMES:-iPhone 14,iPhone 17}"
140181 local runtime=" ${IOS_RUNTIME:- 18.5} "
141182 for device in " ${devices[@]} " ; do
0 commit comments