Swift 命令速查表 - Swift 常用命令与 iOS 开发大全

这套速查给用 Swift 交付 iOS/macOS 应用、命令行工具或服务端代码的开发者,横跨两条工具链:Swift / SwiftPM 的命令行,以及 xcodebuild / xcrun simctl。覆盖从脚本编译运行、初始化并构建 Swift 包、对某个 scheme 构建/测试/归档,到驱动模拟器,再加上 let/var、可选绑定、map/filter/reduce 等语法惯用法和断言调试。与一条条堆 Swift 命令不同,条目沿"编译→测试→归档→模拟器运行"的真实循环编排。读完应能把一个包从 swift package init 一路带到通过的 swift test,并在终端驱动整个 Xcode scheme。

编程语言·共 34 条命令·最后更新 2026-07-21
swiftxcodeios

典型使用场景

面向要在命令行或 Xcode 之外直接跑 Swift 的开发者,以及需要跨 iOS/macOS 复用同一份构建脚本的 CI 维护者。本表覆盖三条主线:swift 解释器与 swift package / swift build / swift test 的包工作流、xcodebuild 与 xcrun simctl 的无 UI 构建与模拟器操作、以及语言层面最容易出错的 optional 解包与集合高阶函数。适合「CI 上跑测试」「本地想快速验证一段算法」这类不需要打开完整 IDE 的场景。

编译与运行 6

swift main.swift
运行 Swift 脚本
swiftc main.swift -o main
编译为可执行文件
swift main.swiftc
进入 REPL
swift -e "print("Hello")"
执行单行代码
swift package init --type executable
初始化可执行包
swift package init --type library
初始化库包

Swift Package Manager 8

swift build
按 Package.swift 编译项目,产物在 .build 目录,调试期最常用
swift build -c release
以 release 优化编译,交付或压测性能时用这个构建
swift run
编译并运行可执行 target,等同 build 再手动跑产物
swift test
跑 XCTest 单元测试,失败会以非零退出码返回,可在 CI 里拦截回归
swift package resolve
按 Package.resolved 拉齐依赖到锁定版本,首次 clone 后先跑它
swift package update
把依赖更新到满足约束的最新版本并刷新解析文件
swift package reset
清空 .build 缓存重新完整构建,解决疑难的增量编译问题
swift package show-dependencies
以树形打印依赖关系,看清每个包的来源与版本

Xcode 命令行 7

xcodebuild -list
列出工程里的 scheme 与 target,先确定要用哪个名字
xcodebuild -scheme MyApp build
对指定 scheme 做一行构建,配合 -destination 可指定模拟器/真机
xcodebuild -scheme MyApp test
运行该 scheme 的测试并在终端输出结果,适合 CI 无 UI 环境下跑测试
xcodebuild archive -scheme MyApp
打包归档出用于分发/上架的 .xcarchive,可再导出 ipa
xcrun simctl list devices
列出所有可用模拟器及其 UDID/状态,作为后续 boot/install 的参数来源
xcrun simctl boot <device-id>
启动指定模拟器(用 simctl list 拿到的 id)
xcrun simctl install booted MyApp.app
把构建好的 .app 安装进当前已启动的模拟器,供手工点验

常用语法 8

var name: String = "Swift"
用 var 声明可变变量,赋值后仍可改
let age: Int = 18
用 let 声明常量,赋值后不可再改,Swift 里默认值优先用 let
if let value = optional { ... }
可选绑定:解开 optional 后在此作用域内以非空 value 使用,躲开不定解包
guard let value = optional else { return }
提前退出:条件不满足立即 return/continue,把坏路径收敛在函数开头
array.map { $0 * 2 }
对每个元素应用闭包,返回长度相同的新数组,常做模型转换
array.filter { $0 > 5 }
保留满足闭包条件的元素,返回新数组不动原数组
array.reduce(0) { $0 + $1 }
从初值 0 起把相邻结果累积为一个值,求和/拼接常用
for (index, value) in array.enumerated()
带索引遍历,同时拿到位置 index 与元素 value

调试与性能 5

print("debug: \(variable)")
打印调试信息
debugPrint(object)
详细打印(含类型)
assert(condition, "message")
断言(debug 模式)
precondition(condition, "message")
前置条件(所有模式)
Instruments
性能分析工具(Xcode 内置)

参数矩阵

参数作用示例
swift build -c release带优化的构建,交付与压测性能时用;调试期仍用默认 debugswift build -c release
guard let ... else可选解包 + 提前退出,把坏路径收敛在函数开头guard let value = optional else { return }
xcodebuild -scheme MyApp test在无 UI 环境下跑该 scheme 的测试,适合 CIxcodebuild -scheme MyApp test

易错点与避坑指南

现象运行时报 fatal error: unexpectedly found nil。

原因对 optional 用了强制解包 !,而该值在某些分支确实为 nil。

处置用 if let value = optional { ... } 或 guard let value = optional else { return } 处理分支。

现象改了一行代码,swift build 却报告与改动无关的编译错误。

原因.build 增量缓存与源码状态不一致。

处置执行 swift package reset 清空缓存后重新 swift build。

现象依赖拉到最新版本后编译失败,CI 挂了但本地没事。

原因本地已有一份旧的 Package.resolved,CI 从零解析拿到更新版本。

处置先 swift package resolve 锁定版本,再把 Package.resolved 一起提交;确认无误后才 swift package update。

现象assert 的断言在 release 包里被跳过,问题上线后才暴露。

原因assert 只在 debug 配置生效,release 下被移除。

处置关键不变量改用 precondition(condition, "message"),它在所有模式下都会求值。

排障路径

  1. 1确认工程里有哪些 scheme 再选构建目标

    xcodebuild -list

    先拿到 scheme 名,否则 -scheme 会直接失败并提示找不到目标。

  2. 2拿到模拟器 id 并安装构建产物做手工验证

    xcrun simctl install booted MyApp.app

    id 来自 xcrun simctl list devices,装之前先让模拟器处于 booted 状态。

  3. 3确认依赖树与锁定版本是否符合预期

    swift package show-dependencies

    以树形打印每个依赖的来源与版本,用来核对版本冲突和意外引入的间接依赖。

命令示例

跑一段脚本与编译成可执行文件

swift main.swift swiftc main.swift -o main

第一条直接解释执行脚本,第二条产出可执行文件;swift -e "print(...)" 可以只跑一行代码。

初始化可执行包并跑测试

swift package init --type executable swift build swift test

产物落在 .build 目录;swift test 失败时返回非零退出码,CI 可据此拦截回归。

release 构建与依赖版本对齐

swift build -c release swift package resolve swift package show-dependencies

全新 clone 后先 resolve,再靠 show-dependencies 看清每个包的来源与锁定版本。

可选解包与集合高阶函数的常见组合

if let value = optional { print(value) } array.map { $0 * 2 } array.filter { $0 > 5 } array.reduce(0) { $0 + $1 }

三个高阶函数都返回新值、不改原数组;map 做模型转换,filter 筛出满足条件的元素,reduce 从初值累积。

常见坑与注意事项

  • assert 只在 debug 模式生效,release 构建里不会执行;需要所有模式都拦下来的前置条件请用 precondition。
  • 给可选类型强解包(!)在值为 nil 时直接触发运行期崩溃,坏路径请交给 if let 或 guard let 处理。
  • swift build -c release 打开优化后编译明显变慢,调试期用默认 debug 配置,别把两者混在同一个循环里。
  • swift package reset 会清空 .build 做全量重建,下次构建耗时大增,只在增量编译报错与改动无关时使用。
  • xcrun simctl 的设备 id 只能从 xcrun simctl list devices 的输出里取;boot 之前也必须先确认目标设备处于可用状态。

提示

  • swift package init 生成的 Package.swift 是 SPM 的配置文件。
  • 可选类型 ? 是 Swift 空安全的核心,尽量用 if let / guard let 解包。
  • xcodebuild 命令行适合 CI/CD 自动化构建和测试。

常见问题

swift run 和先 swift build 再手动跑产物有什么区别?

swift run 内部就是先按 Package.swift 编译再执行可执行 target 的产物,差别只在于省掉了你手动找 .build 目录下产物路径这一步。调试期想在断点前后插入 swift build 单独看编译结果时,两步走更清楚;CI 里只想确认产物能不能跑起来,用 swift run 一条命令就够。另外 swift run 只会作用于可执行 target,库包执行它没有意义。

为什么本地能编过,swift test 却在 CI 上失败?

最常见的原因是依赖版本没锁死。本地已经有 .build 缓存和已解析的依赖,而 CI 是全新 clone,必须先 swift package resolve 把依赖拉到 Package.resolved 锁定的版本;只有这个文件是最新且被提交进版本库时,两边才会一致。如果依赖的 Package.swift 在 CI 上被更新过,就要用 swift package show-dependencies 打印依赖树,逐个确认每个包的来源与版本是否符合预期,再决定是提交 Package.resolved 还是回退约束。

if let 和 guard let 到底该怎么选?

两者的差别是「解包失败之后要不要离开当前作用域」。if let value = optional 后面跟代码块,解包失败就整块跳过,控制流保持在一个分支里;guard let value = optional else { return } 解包失败时立即 return(循环里是 continue),因此它之后的代码里 value 已经是解包后的非可选值,不用再写问号。实践上把 guard 放在函数或循环开头集中处理坏路径,剩下主体就能当作非可选值直接写。

swift package reset 什么时候值得用?

它清空 .build 缓存并重新做一次完整构建,属于「前面的手段都试过了」这一档的处置。适用信号是增量编译报出与刚改动的代码无关的错误,或者改了一行却看到明显陈旧的报错信息。代价是下一次 swift build 要全量编译,耗时明显变长,所以不要当成日常操作的默认一步,先确认错误确实指向缓存而不是依赖或代码本身。

模拟器上验证一个构建产物需要哪几步?

顺序是固定的四步:先用 xcodebuild -list 确认 scheme 名字,用它做 xcodebuild -scheme MyApp build 产出 .app;再用 xcrun simctl list devices 拿到目标设备的 UDID 并 xcrun simctl boot 该 id;接着 xcrun simctl install booted MyApp.app 把产物装进已启动的模拟器;最后手动点验。UDID 只能从 simctl list 的输出里取,猜一个 id 一定会失败。

官方参考来源

下方为命令对应的官方权威文档,供你核对最新用法与深入查阅。

由 巧匠 维护

公开更新于 2026年7月21日,内容持续校对官方文档。

联系我们

命令或描述有误?提交反馈、商务合作或产品建议都可发送邮件给我们。

联系我们