Highlight
这场 Session 覆盖了 Xcode 16 在开发全流程中的更新。编辑方面,代码补全用上了设备端训练的 Swift/Apple SDK 模型,能根据函数名和注释上下文给出更贴切的建议,这完全依赖 Apple Silicon 的本地算力。
核心内容
Xcode 16 的更新覆盖了编码、构建、调试、测试、性能分析五个阶段。先看一个痛点:Preview 里要用 @State,必须写一个只包含 @State 属性的包装视图,再在 Preview 里引用它。每个需要 Binding 的视图都要这么干,代码量翻倍,维护成本也随之上升。@Previewable 宏直接解决了这个问题——在 Preview 块里声明 @Previewable @State var currentFace = ...,预览系统在幕后生成包装视图,你只需要写两行代码。另一个痛点是多个 Preview 共享环境数据(比如 SwiftData 的 ModelContainer),每个 Preview 各自初始化一份,既重复又拖慢速度。PreviewModifier 协议让共享数据只初始化一次,由预览系统缓存。
构建方面,过去模块依赖扫描和模块编译是隐式嵌在源文件编译里的,构建日志只显示 “Compile xxx.swift”,出错时很难定位是模块问题还是源码问题。Explicit Modules 把编译拆成三个显式阶段:扫描依赖、构建模块、编译源码。每个阶段在构建日志和 Timeline 中独立可见,并行性更好,模块相关报错也清晰得多。C/Objective-C 默认开启,Swift 需要在 Build Settings 中手动 opt-in。
详细内容
Previewable 宏(03:37)让 @State 等属性包装器直接在 Preview 块中使用:
#Preview {
@Previewable @State var currentFace = RobotFace.heart
RobotFaceSelectorView(currentFace: $currentFace)
}
关键点:
@Previewable修饰@State,预览系统在幕后创建包装视图,无需手写currentFace可以用$currentFace传 Binding,和正常@State行为一致- 只需两行代码即可 Preview 一个需要 Binding 的视图
PreviewModifier 协议(04:40)解决预览间共享数据的问题:
struct SampleRobotNamer: PreviewModifier {
typealias Context = RobotNamer
static func makeSharedContext() async throws -> Context {
let url = URL(fileURLWithPath: "/tmp/local_names.txt")
return try await RobotNamer(url: url)
}
func body(content: Content, context: Context) -> some View {
content.environment(context)
}
}
关键点:
makeSharedContext()是async throws,可以异步加载数据,且同类 Modifier 只调用一次,预览系统自动缓存body(content:context:)将共享数据注入视图层级,这里用.environment()注入- 配合
PreviewTrait扩展可以把调用点压缩到.sampleNamer一个 trait
Swift Testing 框架(13:42)替代部分 XCTest 用法:
import Testing
@testable import BOTanist
@Test
func plantingRoses() {
let plant = Plant(type: .rose)
let expected = Plant(type: .rose, style: .graft)
#expect(plant == expected)
}
关键点:
@Test宏标记测试函数,函数名随意取,不再受test前缀限制#expect接受任意布尔表达式,断言失败时自动输出值差异详情- 测试函数可用
.tags()附加自定义 Tag,按 Tag 分组运行或从 Test Plan 中排除
Explicit Modules 构建(06:26)将编译拆为扫描依赖、构建模块、编译源码三个阶段。构建日志中可见 “Scan dependencies”、“Compile Swift module” 等独立条目,Timeline 中也能看到各阶段的耗时分布。C/ObjC 默认开启;Swift 在 Build Settings 中开启 “Enable Explicitly Built Modules” 即可。另外,Xcode 16 还支持在 Swift Package 解析完成前就启动构建(07:15)。
调试改进:DWARF5 成为 macOS Sequoia / iOS 18 部署目标的默认调试符号格式,dSYM 更小、符号查找更快。Thread Performance Checker 新增慢启动和过量磁盘写入诊断。Unified Backtrace View(10:56)在 Debug Bar 开启后,可以连续滚动查看调用栈每一帧的代码和变量值,无需逐帧点击。RealityKit 调试器(12:16)可一键捕获空间应用的 Entity 层级快照,在 Xcode 内以 3D 视图浏览。
Instruments Flame Graph(19:42)提供调用栈的面积可视化,左侧是最耗时的调用路径。Session 演示了用 Flame Graph 定位串行 asset.load() 循环,改为并行 Task Group 后启动时间显著缩短:
await withDiscardingTaskGroup { group in
for asset in allAssets {
group.addTask {
asset.load()
}
}
}
核心启发
-
做什么:在项目中逐步启用 Swift 6 Upcoming Features。为什么值得做:数据竞争从运行时偶现变成编译期必现,越早修成本越低。怎么开始:在 Build Settings 的 “Swift Compiler - Upcoming Features” 中逐个开启(如 Isolated Global Variables、Strict Concurrency),每次构建只面对一类警告,修完再开下一个。
-
做什么:用 PreviewModifier 封装预览共享环境。为什么值得做:SwiftData ModelContainer、Mock 网络层等在多个 Preview 中重复初始化,既冗余又拖慢预览刷新。怎么开始:定义一个
PreviewModifier,在makeSharedContext()中初始化 ModelContainer 或 Mock 数据,扩展PreviewTrait添加.myModifiertrait,所有 Preview 用同一 trait 即可共享缓存数据。 -
做什么:新测试文件用 Swift Testing 替代 XCTest。为什么值得做:
@Test宏 +#expect写法更简洁,参数化测试天然并行,Tag 机制比 XCTest 的 filter 更灵活。怎么开始:新测试文件 import Testing,用@Test func xxx()标记,#expect做断言;已有 XCTest 不受影响,两者共存。 -
做什么:为 Swift 目标开启 Explicit Modules。为什么值得做:编译拆为显式阶段后并行度更高、模块报错更清晰,lldb 表达式求值也能复用模块构建产物,调试更快。怎么开始:Build Settings 中开启 “Enable Explicitly Built Modules”,观察构建日志和 Timeline 中新增的 “Scan dependencies” / “Compile Swift module” 条目。
关联 Session
- Migrate your app to Swift 6 — 如何逐步启用 Swift 6 并发安全特性
- Meet Swift Testing — Swift Testing 框架入门,涵盖 @Test、#expect、参数化测试
- Demystify explicitly built modules — 深入讲解 Explicit Modules 的三阶段构建模型
- Break into the RealityKit debugger — 用新的 RealityKit 调试器检查空间应用 Entity 层级
- Run, break, and inspect: Explore effective debugging in LLDB — LLDB 高级调试技巧与 Xcode 16 调试工作流
评论
GitHub Issues · utterances