从 iOS 15 模拟器不可用到 Xcode 26.6 只剩 Vision Pro

本文目录

这次排查最初并不是从 Vision Pro 开始的,而是为了在 iOS 15 模拟器上验证应用兼容性。整个故障定位、修复方案设计和验证过程由我与 Codex 协作完成。

Xcode 26 的 Components 页面仍然提供 iOS 15.0 Simulator。Runtime 能够下载和安装,但安装完成后却无法正常选择或创建可用的 iPhone 模拟器。随后我又尝试了 iOS 15.5,并在 Xcode 26.5 与 26.6 之间切换验证。就在继续排查旧 Runtime 可用性时,问题进一步表现为:simctl 的设备类型列表只剩下 Apple Vision Pro 4K,Xcode 也无法正常创建和选择 iPhone、iPad 模拟器。

最后确认:问题不在 Xcode.app 本身,而是 Xcode 27 beta 留在 /Library/Developer 中的全局 CoreSimulator DeviceTypes 与 Xcode 26.6 不兼容。删除或重装 Xcode.app 不会自动回滚这部分系统级组件。

本文按实际发生顺序,记录从“iOS 15 Runtime 已安装却不能使用”到定位 DeviceTypes 版本错配,再到离线修复与 iOS 15.5 实际运行验证的全过程。环境是同一块磁盘上的两套 macOS,且两套系统拥有各自独立的 Data 卷。

起点:iOS 15 Runtime 能安装,却不能使用

为了验证 iPerfman 的 iOS 15 fallback 图表,我先在 Xcode 26 的 Components 页面下载了 iOS 15.0 Simulator。Xcode 明确提供下载入口,安装也能完成,但 Runtime 没有变成一个可正常创建和启动的 iPhone 模拟器。

由于 iOS 15.0 无法使用,我继续下载了 iOS 15.5,并先后用 Xcode 26.5、Xcode 26.6 重新检查。这排除了“某一个下载包偶然损坏”的简单情况,却仍未解释为什么已经安装的 Runtime 不能使用。

这里容易混淆三个概念:

  • Xcode:开发工具本体,例如 Xcode 26.6。
  • Runtime:模拟器系统版本,例如 iOS 15.0、iOS 15.5。
  • DeviceType:模拟设备模板,例如 iPhone 13、iPhone 17 Pro。

只有 Runtime 并不足以创建模拟器;CoreSimulator 还必须能提供与之匹配的 DeviceType。也正是在检查这一层时,后续的 Vision Pro 异常才浮出水面。

后续症状:DeviceType 只剩 Vision Pro

稳定系统使用的是 Xcode 26.6:

bash
1
2
xcode-select -p
xcodebuild -version

输出:

text
1
2
3
/Applications/Xcode.app/Contents/Developer
Xcode 26.6
Build version 17F113

但设备类型只剩一个:

bash
1
xcrun simctl list devicetypes
text
1
2
== Device Types ==
Apple Vision Pro 4K (com.apple.CoreSimulator.SimDeviceType.Apple-Vision-Pro-4K)

到这里才发现,iOS 15 不是唯一的问题:simctl 根本没有加载正常的 iPhone、iPad DeviceTypes。Runtime 文件仍然存在,但缺少可用的设备模板,自然无法组合出可创建、可启动的 iOS 模拟器。

找到版本错配

先检查全局 CoreSimulator framework:

bash
1
2
3
4
5
6
7
defaults read \
/Library/Developer/PrivateFrameworks/CoreSimulator.framework/Resources/Info \
CFBundleVersion

defaults read \
/Library/Developer/PrivateFrameworks/CoreSimulator.framework/Resources/Info \
DTXcodeBuild

稳定版 framework 已经是与 Xcode 26.6 匹配的版本:

text
1
2
CFBundleVersion = 1051.55
DTXcodeBuild = 17F109

再检查全局 DeviceType:

bash
1
2
3
4
5
/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' \
'/Library/Developer/CoreSimulator/Profiles/DeviceTypes/iPhone 17 Pro.simdevicetype/Contents/Info.plist'

/usr/libexec/PlistBuddy -c 'Print :DTXcodeBuild' \
'/Library/Developer/CoreSimulator/Profiles/DeviceTypes/iPhone 17 Pro.simdevicetype/Contents/Info.plist'

这里得到的是:

text
1
2
CFBundleVersion = 394
DTXcodeBuild = 27A5194c

而 Xcode 26.6 自带的 XcodeSystemResources.pkg 中,同一批 DeviceTypes 应该是:

项目Xcode 27 beta 残留Xcode 26.6 包内版本
CFBundleVersion394381.1
DTXcode27002660
DTXcodeBuild27A5194c17F103

到这里,问题已经很明确:Xcode 26.6 正在读取 Xcode 27 beta 写入的全局 DeviceTypes。

为什么重装 Xcode 没用

新版 Xcode 会把部分 CoreSimulator 组件安装到 /Library/Developer。这是系统级位置,不属于 /Applications/Xcode.app。

因此:

  1. 删除 Xcode.app 不会删除或回滚 /Library/Developer 中的组件。
  2. 再安装 Xcode 26.6 时,安装器看到已安装 bundle 的版本号 394 高于包内的 381.1,可能拒绝降级。
  3. SIP 会保护当前启动系统中的相关目录,直接替换可能得到 Operation not permitted,即使使用 sudo 也不代表一定可写。

我也尝试过从 Xcode 26.6 的系统资源包重新安装,但版本检查和当前系统保护都阻止了覆盖。这说明继续反复删除 Xcode.app 并不能触及根因。

先用 --profiles 验证根因

在改动系统目录之前,可以先提取 Xcode 26.6 自带的 Profiles:

bash
1
2
3
4
5
6
7
repair_tmp=$(mktemp -d /tmp/xcode266-repair.XXXXXX)

pkgutil --expand-full \
/Applications/Xcode.app/Contents/Resources/Packages/XcodeSystemResources.pkg \
"$repair_tmp/XcodeSystemResources"

profile_root="$repair_tmp/XcodeSystemResources/Payload/Library/Developer/CoreSimulator/Profiles"

也可以先验证安装包签名:

bash
1
2
pkgutil --check-signature \
/Applications/Xcode.app/Contents/Resources/Packages/XcodeSystemResources.pkg

然后让 simctl 临时使用刚提取的 Profiles:

bash
1
xcrun simctl --profiles "$profile_root" list devicetypes

这时 iPhone、iPad、Apple Watch、Apple TV 和 Vision Pro 的完整列表全部恢复,证明 Xcode 26.6 自带的 Profiles 可以正常工作。

还可以使用独立的 Simulator set 创建测试设备,避免污染默认设备集:

bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
verification_set=$(mktemp -d /tmp/xcode266-verification-set.XXXXXX)

verification_udid=$(xcrun simctl \
--set "$verification_set" \
--profiles "$profile_root" \
create "Xcode 26.6 Repair Check" \
com.apple.CoreSimulator.SimDeviceType.iPhone-17-Pro \
com.apple.CoreSimulator.SimRuntime.iOS-26-5)

xcrun simctl --set "$verification_set" \
--profiles "$profile_root" boot "$verification_udid"

xcrun simctl --set "$verification_set" \
--profiles "$profile_root" bootstatus "$verification_udid" -b

测试设备成功启动,Settings 也能正常打开。这一步把问题进一步缩小到了全局 DeviceTypes。

需要注意:--profiles 只对当前 simctl 调用生效。随后直接执行普通的 xcrun simctl list devicetypes,仍然只会看到 Vision Pro,因此它是诊断和临时验证手段,不是永久修复。

永久修复:从另一套 macOS 替换离线 Data 卷

以下操作必须从另一套 macOS 或 Recovery 对离线的稳定系统 Data 卷执行。不要在当前启动系统上直接删除 /Library/Developer,也不要使用宽泛的递归删除命令。务必先确认卷身份并保留可回滚备份。

我的两套 macOS 虽然位于同一块磁盘,但各自拥有独立的 Data 卷。因此可以启动到 beta 系统,让稳定系统的 Data 卷作为普通数据卷挂载,再替换其中的 DeviceTypes。

稳定系统的 Data 卷挂载在:

text
1
/Volumes/Data

我提前从 Xcode 26.6 的 XcodeSystemResources.pkg 中提取了 DeviceTypes,并验证:

  • DTXcodeBuild 为 17F103。
  • DeviceType 数量为 124。
  • 目标目录仍是 Xcode 27 beta 的 27A5194c,数量同样不少于 120。
  • 当前启动系统不是要修复的稳定系统。

确认无误后,只移动精确的目标目录并复制兼容版本:

bash
1
2
3
4
5
6
7
8
9
stable_data='/Volumes/Data'
source_profiles='/Users/Shared/Xcode266-CoreSimulator-Repair/DeviceTypes'
target_profiles="$stable_data/Library/Developer/CoreSimulator/Profiles/DeviceTypes"
backup_profiles="$stable_data/Library/Developer/CoreSimulator/Profiles/DeviceTypes.xcode27-394-backup"

sudo mv "$target_profiles" "$backup_profiles"
sudo ditto "$source_profiles" "$target_profiles"
sudo chown -R root:wheel "$target_profiles"
sudo chown root:admin "$target_profiles"

这里使用 mv 保留旧目录,而不是删除。若复制或验证失败,可以把备份移回原位。

实际执行时,我还在脚本中加入了这些保护:

  • 校验稳定 Data 卷的 APFS Volume Group UUID。
  • 拒绝对当前启动系统执行。
  • 同时校验来源与目标的 build 和文件数量。
  • 若备份目录已经存在则停止,避免覆盖上一次备份。
  • 复制后再次校验;失败就自动回滚。

修复结果

重新启动到稳定系统后,检查全局 DeviceTypes:

bash
1
2
3
4
5
6
7
8
/usr/libexec/PlistBuddy -c 'Print :DTXcodeBuild' \
'/Library/Developer/CoreSimulator/Profiles/DeviceTypes/iPhone 17 Pro.simdevicetype/Contents/Info.plist'

find /Library/Developer/CoreSimulator/Profiles/DeviceTypes \
-maxdepth 1 -name '*.simdevicetype' | wc -l

xcrun simctl list devicetypes
xcrun simctl list runtimes

结果:

  • DeviceTypes build 为 17F103,共 124 个。
  • 安装后的目录与 Xcode 26.6 包内来源执行 diff -qr 无差异。
  • simctl list devicetypes 恢复完整的 iPhone、iPad、Watch、TV 和 Vision 设备列表。
  • iOS 15.5、iOS 18.6、iOS 26.5 与 tvOS 26.5 Runtime 均可识别。
  • iPhone 17 Pro / iOS 26.5 成功启动并打开 Settings。
  • iPerfman 在 iOS 15.5 模拟器中成功启动并打开 Settings。
  • 没有产生新的 CoreSimulatorBridge 崩溃报告。

确认稳定运行前,我保留了两个备份:

text
1
2
/Library/Developer/CoreSimulator/Profiles/DeviceTypes.xcode27-394-backup
/Library/Developer/PrivateFrameworks/CoreSimulator.framework.xcode27-1155.4-backup

经验总结

这次问题最关键的判断是:Xcode.app 的版本正确,不等于系统正在使用的 CoreSimulator 全局组件也正确。

以后在稳定版与 beta 版 Xcode 之间切换时,我会优先检查:

bash
1
2
3
4
xcode-select -p
xcodebuild -version
xcrun simctl list devicetypes
xcrun simctl list runtimes

如果 simctl 的设备类型突然大量消失:

  1. 先比较 /Library/Developer 中 CoreSimulator framework 与 DeviceTypes 的 build。
  2. 用 Xcode 自带包提取 Profiles,再通过 simctl --profiles 做无侵入验证。
  3. 不要把“删除 Xcode.app”当作系统级组件的回滚方案。
  4. 需要替换受保护目录时,优先从另一套 macOS 或 Recovery 操作离线 Data 卷。
  5. 精确移动目标目录并保留备份,不要直接清空整个 /Library/Developer。

参考

本文由 Codex 协助排查 CoreSimulator 故障、验证修复结果并整理成文。