这次排查最初并不是从 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:
1 | xcode-select -p |
输出:
1 | /Applications/Xcode.app/Contents/Developer |
但设备类型只剩一个:
1 | xcrun simctl list devicetypes |
1 | == Device Types == |
到这里才发现,iOS 15 不是唯一的问题:simctl 根本没有加载正常的 iPhone、iPad DeviceTypes。Runtime 文件仍然存在,但缺少可用的设备模板,自然无法组合出可创建、可启动的 iOS 模拟器。
找到版本错配
先检查全局 CoreSimulator framework:
1 | defaults read \ |
稳定版 framework 已经是与 Xcode 26.6 匹配的版本:
1 | CFBundleVersion = 1051.55 |
再检查全局 DeviceType:
1 | /usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' \ |
这里得到的是:
1 | CFBundleVersion = 394 |
而 Xcode 26.6 自带的 XcodeSystemResources.pkg 中,同一批 DeviceTypes 应该是:
| 项目 | Xcode 27 beta 残留 | Xcode 26.6 包内版本 |
|---|---|---|
CFBundleVersion | 394 | 381.1 |
DTXcode | 2700 | 2660 |
DTXcodeBuild | 27A5194c | 17F103 |
到这里,问题已经很明确:Xcode 26.6 正在读取 Xcode 27 beta 写入的全局 DeviceTypes。
为什么重装 Xcode 没用
新版 Xcode 会把部分 CoreSimulator 组件安装到 /Library/Developer。这是系统级位置,不属于 /Applications/Xcode.app。
因此:
- 删除 Xcode.app 不会删除或回滚
/Library/Developer中的组件。 - 再安装 Xcode 26.6 时,安装器看到已安装 bundle 的版本号
394高于包内的381.1,可能拒绝降级。 - SIP 会保护当前启动系统中的相关目录,直接替换可能得到
Operation not permitted,即使使用sudo也不代表一定可写。
我也尝试过从 Xcode 26.6 的系统资源包重新安装,但版本检查和当前系统保护都阻止了覆盖。这说明继续反复删除 Xcode.app 并不能触及根因。
先用 --profiles 验证根因
在改动系统目录之前,可以先提取 Xcode 26.6 自带的 Profiles:
1 | repair_tmp=$(mktemp -d /tmp/xcode266-repair.XXXXXX) |
也可以先验证安装包签名:
1 | pkgutil --check-signature \ |
然后让 simctl 临时使用刚提取的 Profiles:
1 | xcrun simctl --profiles "$profile_root" list devicetypes |
这时 iPhone、iPad、Apple Watch、Apple TV 和 Vision Pro 的完整列表全部恢复,证明 Xcode 26.6 自带的 Profiles 可以正常工作。
还可以使用独立的 Simulator set 创建测试设备,避免污染默认设备集:
1 | verification_set=$(mktemp -d /tmp/xcode266-verification-set.XXXXXX) |
测试设备成功启动,Settings 也能正常打开。这一步把问题进一步缩小到了全局 DeviceTypes。
需要注意:--profiles 只对当前 simctl 调用生效。随后直接执行普通的 xcrun simctl list devicetypes,仍然只会看到 Vision Pro,因此它是诊断和临时验证手段,不是永久修复。
永久修复:从另一套 macOS 替换离线 Data 卷
以下操作必须从另一套 macOS 或 Recovery 对离线的稳定系统 Data 卷执行。不要在当前启动系统上直接删除
/Library/Developer,也不要使用宽泛的递归删除命令。务必先确认卷身份并保留可回滚备份。
我的两套 macOS 虽然位于同一块磁盘,但各自拥有独立的 Data 卷。因此可以启动到 beta 系统,让稳定系统的 Data 卷作为普通数据卷挂载,再替换其中的 DeviceTypes。
稳定系统的 Data 卷挂载在:
1 | /Volumes/Data |
我提前从 Xcode 26.6 的 XcodeSystemResources.pkg 中提取了 DeviceTypes,并验证:
DTXcodeBuild为17F103。- DeviceType 数量为 124。
- 目标目录仍是 Xcode 27 beta 的
27A5194c,数量同样不少于 120。 - 当前启动系统不是要修复的稳定系统。
确认无误后,只移动精确的目标目录并复制兼容版本:
1 | stable_data='/Volumes/Data' |
这里使用 mv 保留旧目录,而不是删除。若复制或验证失败,可以把备份移回原位。
实际执行时,我还在脚本中加入了这些保护:
- 校验稳定 Data 卷的 APFS Volume Group UUID。
- 拒绝对当前启动系统执行。
- 同时校验来源与目标的 build 和文件数量。
- 若备份目录已经存在则停止,避免覆盖上一次备份。
- 复制后再次校验;失败就自动回滚。
修复结果
重新启动到稳定系统后,检查全局 DeviceTypes:
1 | /usr/libexec/PlistBuddy -c 'Print :DTXcodeBuild' \ |
结果:
- 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 崩溃报告。
确认稳定运行前,我保留了两个备份:
1 | /Library/Developer/CoreSimulator/Profiles/DeviceTypes.xcode27-394-backup |
经验总结
这次问题最关键的判断是:Xcode.app 的版本正确,不等于系统正在使用的 CoreSimulator 全局组件也正确。
以后在稳定版与 beta 版 Xcode 之间切换时,我会优先检查:
1 | xcode-select -p |
如果 simctl 的设备类型突然大量消失:
- 先比较
/Library/Developer中 CoreSimulator framework 与 DeviceTypes 的 build。 - 用 Xcode 自带包提取 Profiles,再通过
simctl --profiles做无侵入验证。 - 不要把“删除 Xcode.app”当作系统级组件的回滚方案。
- 需要替换受保护目录时,优先从另一套 macOS 或 Recovery 操作离线 Data 卷。
- 精确移动目标目录并保留备份,不要直接清空整个
/Library/Developer。
参考
本文由 Codex 协助排查 CoreSimulator 故障、验证修复结果并整理成文。