iOS 27 CI 还要装 Simulator 吗?2026 节点判断

CI 日志里已经出现“构建成功”,但测试任务仍要求启动 iOS Simulator;或者构建节点下载了完整运行时,却只负责生成制品。

最快的判断是:不要统一删除 Simulator。截至 2026 年 9 月 8 日,Xcode 27 Beta 6 已确认 UIKit Interface Builder 文档默认可用 toolchain 模式编译,部分纯构建任务可以不下载 Simulator;应用宿主测试、UI 测试和运行时兼容验证仍应保留 Simulator 或真机。建议先把远程 Mac 拆成轻量构建池与完整测试池,再用同一提交双轨试跑。

这篇文章适合三类团队:

  • 只做编译、静态检查和制品生成,希望缩减环境依赖的构建工程师。
  • 维护 XCTest、UI 自动化或多系统版本测试,需要确认 Simulator 边界的测试团队。
  • 正在调整远程 Mac 节点池、缓存、恢复策略和 CI 路由的 DevOps、研发平台负责人。

Last updated:2026 年 9 月 8 日。本文技术判断核实自 Apple 的 Xcode 27 Beta 6 发布说明、Xcode 系统要求、Xcode 构建与测试文档。Xcode 27 和 iOS 27 目前仍按 Beta 资料处理。

“安装 Xcode”并不等于“安装 Simulator runtime”。CI 节点至少要区分以下对象:

对象 作用 是否等于 Simulator
iOS SDK 编译、链接 iOS 代码所需的头文件、模块和库 ❌ 不是
Simulator runtime 提供模拟 iOS 系统运行环境 ✅ 是运行时
模拟设备 具体的 iPhone 或 iPad 模拟设备实例 ✅ 依赖运行时
Interface Builder 编译模式 编译 Storyboard、XIB 等 UIKit 文档 ❌ 不等于设备运行
测试 destination 告诉 xcodebuild 测试在哪个平台和设备上执行 可能要求 Simulator 或真机

Xcode 27 Beta 6 的变化集中在最后两个编译环节:Apple 引入了面向 UIKit 文档的 toolchain 编译模式,并说明该模式允许在不下载 Simulator 的情况下编译相关 Interface Builder 文档。官方发布说明同时给出了回退方式,包括将 IBC_COCOATOUCH_COMPILER_MODE 设为 simulator,或在手动调用 ibtool 时传入对应参数。

这并不代表应用已经“可以运行”。Apple 的运行文档仍将“在模拟设备或物理设备上构建并运行”作为测试应用的路径,并明确提醒 Simulator 不能完全复制真实设备的性能和特性。运行模拟或物理设备上的应用因此,编译成功只能证明当前构建路径完成,不能证明测试节点已经可以精简。

纯构建可以先试无运行时节点

如果任务只包含源码编译、链接、资源处理、静态检查、归档前构建或制品上传,构建工程师可以先创建一个不主动下载 Simulator runtime 的候选节点。

但“纯构建”必须按实际命令定义,而不是按 Job 名称定义。建议在同一提交上分别执行:

xcodebuild build \
  -workspace App.xcworkspace \
  -scheme App \
  -configuration Release

然后检查日志中是否出现:

  • platform=iOS Simulator
  • 指定的 Simulator destination
  • simctl、模拟设备启动或 runtime 路径
  • 隐式下载或初始化运行时的步骤
  • Storyboard、XIB 或 ibtool 的编译错误

Xcode 的命令行工具包括 xcodebuildsimctldevicectl,但“工具存在”不代表每次构建都会启动模拟设备。Xcode 命令行工具参考真正要记录的是本次 Job 是否请求了 destination,以及是否产生了运行时调用。

Xcode 27 Beta 6 的边界

Apple 当前已确认两点:

  1. Xcode 27 只能安装并运行在 Apple Silicon Mac 上。
  2. UIKit Interface Builder 文档默认使用 toolchain 模式编译,目标是让构建服务器脱离 Simulator 下载。

Xcode 27 Beta 6 的系统要求页面显示,该版本需要 macOS Tahoe 26.4 或更高版本,并对应 iOS 27 SDK。Xcode 系统要求表这些是工具链和宿主环境要求,不应被误读为“所有 CI 工作负载都不再需要 Simulator”。

构建设置的优先级也会影响判断。Xcode 文档说明,命令行传入的构建设置具有最高优先级;项目级、Target 级配置文件和系统默认值可能覆盖或改变最终行为。配置 Target 构建设置因此,项目中如果存在自定义 .xcconfig、Target 覆盖值或脚本参数,不能只看 Xcode 图形界面里的默认选项。

Storyboard 和 XIB 项目最容易出现“第一次构建成功,后续任务失败”的假象。原因是旧项目可能包含自定义构建设置、特殊资源、插件或直接调用 ibtool 的脚本。

Apple 的 Build Settings Reference 将 IBC_COCOATOUCH_COMPILER_MODE 定义为控制 CocoaTouch 文档编译模式的设置,同时列出 Storyboard 编译相关的 IBSC_COCOATOUCH_COMPILER_MODE构建设置参考工程维护者应同时检查项目中的 .storyboard.xib、自定义 Run Script 和资源处理脚本,而不是只修改一个全局开关。

建议按以下顺序验收:

  1. 在候选轻量节点清理 Derived Data,避免缓存掩盖真实依赖。
  2. 使用现有项目执行一次普通 build,保存完整日志。
  3. 检查生成的 .storyboardc.nib 和资源目录是否齐全。
  4. 对比原节点和候选节点的产物清单、警告与错误。
  5. 对包含自定义模块、动态字体、复杂 Trait Variation 的界面做启动验证。
  6. 如果出现界面资源错误,记录触发的 Target、配置和资源文件。
  7. 仅对明确触发问题的目标回退到 simulator 模式。

这里不能用“构建退出码为 0”作为唯一标准。界面资源可能在构建阶段生成成功,却在应用启动、Storyboard 加载或 UI 测试阶段才暴露问题。回退策略也应写入 CI 配置,保留一个明确的恢复入口,而不是临时登录节点手动修改。

纯 Swift 逻辑测试

纯 Swift 逻辑测试通常只验证算法、数据转换、状态机或业务规则。如果测试目标不需要启动 iOS 应用进程,也不依赖 UIKit、Core Data 的特定运行时行为或系统权限,团队可以评估将其迁往轻量节点。

但不能把所有名称带有 “UnitTests” 的 Target 都归入这一类。测试目标可能包含 Test Host,也可能链接 UIKit、访问文件系统沙盒或依赖应用生命周期。最终要核对:

  • 测试 Target 是否配置了 Test Host
  • 测试 Scheme 的 destination 是 macOS、iOS Simulator 还是物理设备。
  • 测试产物是否生成 .xctestrun 文件。
  • 测试命令是否需要指定 -destination
  • 结果包是否包含真正执行的测试,而不是只有构建记录。

应用宿主测试

应用宿主测试需要启动被测 App,验证依赖应用进程、Bundle、沙盒、权限或平台框架的行为。这类测试即使不操作界面,也不应因为名字叫 Unit Tests 就直接放入无运行时节点。

Apple 文档说明,xcodebuild test 会输出 Xcode Test Results,也就是 .xcresults 结果包,里面可以包含测试会话、覆盖率和日志。运行测试并解读结果平台团队应将该结果包作为路由依据:如果结果显示测试实际依赖 iOS destination,就把它送往完整测试池。

UI 自动化测试

XCTest UI Tests 需要启动被测应用并操作用户界面。新 Interface Builder 编译模式只解决“界面文档如何编译”,不能替代“应用如何运行”。

UI 测试至少要保留:

  • 已安装且版本匹配的 Simulator runtime。
  • 明确的模拟设备 destination。
  • 可恢复的设备初始化流程。
  • 测试结果包与失败截图、视频或日志。
  • 节点重启后重新启动测试的能力。

并行测试还需要额外观察模拟设备实例的创建、删除、克隆和资源竞争。Apple 的测试文档支持通过 Test Plan 管理测试集合和配置,也支持从命令行指定测试计划。使用 Test Plan 组织测试不要只看 Job 的“编译完成”状态,应确认测试计划中的测试确实执行。

以下评分是面向 CI 架构的编辑判断,不是 Apple 官方性能评级。评分越高,表示越适合对应场景。

方案 适合任务 Simulator 依赖 运维复杂度 节点精简评分
单池保留完整环境 构建、宿主测试、UI 测试混跑 3 / 5
双池拆分 轻量构建与完整测试分工 按任务分配 5 / 5
暂缓迁移 Beta 兼容性未确认、旧项目较多 2 / 5

单池保留

单池最容易落地。所有任务使用相同的 Xcode、SDK、Simulator runtime 和缓存,问题定位也比较集中。

缺点是构建任务会长期承担完整测试环境的存储、初始化和恢复成本。若团队每天大量执行纯构建,这种架构会让不需要运行时的任务继续排队等待测试型节点。

双池拆分

双池方案将任务按依赖分流:

  • 轻量构建池:静态检查、普通构建、资源编译、归档前检查、制品整理。
  • 完整测试池:应用宿主测试、UI 测试、多 iOS 版本验证、真机前置检查。

build-for-testingtest-without-building 很适合验证这种边界。Apple 的命令行技术说明指出,前者用于构建测试相关目标并生成 .xctestrun 文件,后者可以在另一个节点使用这些测试产物执行测试。Build For Testing 与 Test Without Building

可按以下方式试跑:

xcodebuild build-for-testing \
  -workspace App.xcworkspace \
  -scheme App \
  -destination 'generic/platform=iOS'

之后将测试产物交给完整测试节点:

xcodebuild test-without-building \
  -xctestrun path/to/App_iphonesimulator.xctestrun \
  -destination 'platform=iOS Simulator,name=iPhone 16'

具体 destination 需要根据项目目标和已安装 runtime 调整。关键不是照抄设备名称,而是验证构建节点生成的产物是否能被测试节点正确识别。

暂缓迁移

如果工程包含大量旧 Storyboard、直接调用 ibtool 的脚本、非标准插件,或当前 Xcode 27 Beta 仍有未解决的界面资源问题,暂缓删除 Simulator 更稳妥。

暂缓不等于放弃。平台团队可以先保留原节点,同时新增一个可回退的轻量节点。等候选节点连续通过真实项目验证,再修改默认路由。

节点类型 默认安装内容 应接收的任务 不应接收的任务
轻量构建节点 Xcode、必要 SDK、依赖缓存 编译、静态检查、部分资源处理、制品生成 UI 测试、应用宿主测试
完整测试节点 Xcode、SDK、Simulator runtime、模拟设备 XCTest、UI 自动化、Test Plan、多版本验证 无限制地承担所有普通构建
回退节点 与原生产节点一致的完整环境 迁移失败后的重跑、版本对照、发布阻断验证 长期替代所有新节点

这里的“轻量”不是简单删除某个目录。节点还需要考虑 Xcode 版本、SDK 版本、签名证书、依赖缓存、Derived Data 和制品传输。尤其是 build-for-testing 产生的测试产物必须与测试节点的工具链和目标运行时匹配。

发布负责人应使用包含真实复杂度的项目进行双轨验收,而不是创建一个最小 Demo。至少选择同时包含 Storyboard 或 XIB、应用宿主测试和 UI 测试的提交。

建议执行以下 6 步

  1. 冻结同一提交:原节点和候选节点使用完全相同的 Git commit、Scheme、配置文件与依赖锁定文件。
  2. 记录环境边界:保存 Xcode、macOS、SDK、构建设置和测试 destination。
  3. 分别跑纯构建与完整测试:不要用一次全量 Job 代替两种任务。
  4. 传递测试产物:验证 build-for-testing 生成的产物能否在完整测试节点执行。
  5. 比较结果证据:检查 App 产物、Storyboard 编译结果、.xcresults、失败媒体和日志。
  6. 执行重启恢复:重启候选节点后重新运行关键任务,确认缓存、Simulator 和测试设备能恢复。

只有同时满足以下条件,才适合把对应任务正式迁移到轻量构建池:

  • 纯构建连续通过;
  • 日志没有隐式请求 Simulator destination;
  • 没有自动下载或初始化 Simulator runtime;
  • 生成产物与原节点一致;
  • 失败后可以回退到完整节点;
  • 运行时测试仍由测试池承担。

Apple 的 App Store Connect 文档也提醒,上传的构建需要经过系统处理后才会出现在后台,并且构建号会用于识别版本。上传构建到 App Store Connect因此,发布链路不能只验证本地编译结束,还应保留归档、签名、上传和处理状态的独立检查。

Xcode 27 构建 iOS 项目时可以不安装 Simulator 吗?

可以,但范围是“经过验证的构建任务”,不是整个 CI。Xcode 27 Beta 6 的 toolchain 模式让部分 UIKit Interface Builder 文档能够脱离 Simulator 编译;只要任务需要启动 App、执行宿主测试或 UI 自动化,就仍然要保留运行时环境。

哪些 CI 工作负载应保留 Simulator runtime?

需要指定 iOS Simulator destination、启动应用进程、访问 iOS 平台行为或执行 XCTest UI Tests 的任务,都应进入完整测试节点。纯 Swift 逻辑测试可以尝试迁移,但必须先确认没有 Test Host、系统框架运行时依赖和隐式 destination。

Interface Builder 的 toolchain 模式会影响现有 Storyboard 和 XIB 吗?

它改变的是编译路径,不是直接重写界面文件。旧项目、自定义构建设置和直接调用 ibtool 的脚本可能仍然触发兼容问题。迁移时应比较生成的 .storyboardc.nib、启动结果和 UI 测试,而不是只依据构建退出码。

远程 Mac 构建节点和测试节点应该如何拆分?

把静态检查、普通构建、build-for-testing 和制品整理放到轻量节点;把 test-without-building、应用宿主测试、UI 测试和多版本验证放到完整节点。分拆前先用同一提交执行双轨流程,并保留原节点作为回退入口。

判断条件 构建节点 测试节点 处理建议
只做源码编译和静态检查 5 / 5 1 / 5 优先试无 Simulator 构建节点
包含 Storyboard、XIB,但无运行时测试 4 / 5 2 / 5 先验证 toolchain,保留回退配置
包含应用宿主测试 2 / 5 5 / 5 测试任务进入完整节点
包含 XCTest UI Tests 1 / 5 5 / 5 保留 Simulator runtime
需要多版本 iOS 兼容验证 2 / 5 5 / 5 按版本建立测试节点或测试矩阵
Xcode 27 Beta 兼容性尚未稳定 2 / 5 4 / 5 暂缓生产节点精简

对于远程 Mac 环境,推荐先复制一套真实项目到可回退节点,再分别运行普通构建、build-for-testingtest-without-building 和 UI 测试。若需要持续运行的 macOS 节点,可以先参考 NOVAKVM 的远程 Mac 服务入口,按构建池和测试池的实际周期选择环境,而不是先改动生产节点。

如果当前方案是把所有 CI 任务都塞进同一台本地 Mac、Windows 主机配合临时远程桌面,或只使用 Linux 云主机,常见问题是 macOS 工具链无法原生运行、Simulator 测试链路缺失、节点重启后环境难恢复。相比之下,按任务租赁可访问的远程 Mac,更适合先建立独立的构建池或测试池,再根据实际验证结果决定是否长期保留。需要固定地区节点时,也可以进一步查看 NOVAKVM 的 Mac 节点方案

最终判断很明确:不要因为 Xcode 27 的新编译模式,就把所有节点上的 Simulator 一次性删除。 先让纯构建任务脱离运行时,再让应用宿主测试和 UI 测试继续留在完整节点;只有双轨结果、重启恢复和失败回退都通过后,节点精简才具备工程依据。

为 iOS 27 CI 配置合适的 NOVAKVM Mac 节点

使用 NOVAKVM 独立 Mac 节点,将基础构建与需要模拟器的测试任务灵活拆分。

按需租用 M4 Mac,减少本地硬件采购与长期闲置成本,适合团队快速扩展 CI 流水线。

查看定价 →