WWDC 2026 上发布的新一版 SwiftUI,把重点放在两个方向:一是更高效的数据与磁盘访问,二是让常见交互更少写胶水代码。新的 Document 协议支持更高效的磁盘访问和基于快照的更新;列表、网格和 section 的重排 API 得到增强;展示层能力也继续扩展,包括任意 view 上的 swipe actions、更好的 AsyncImage 缓存,以及 Observable 类型的懒状态初始化。
Document 不只是“打开文件”
这次最值得关注的是新的 Document 协议。过去在文档型 App 中,开发者经常需要在“文件读写”“内存状态”“UI 更新”之间手动维持一致性。新协议的方向,是让 SwiftUI 更理解文档数据本身:
- 更高效地访问磁盘,减少不必要的读写压力。
- 通过 snapshot-based updates,让 UI 和文档状态更新更有边界。
- 更适合编辑器、笔记、绘图、项目文件这类“长期打开、频繁修改”的场景。
可以把它理解为 SwiftUI 文档模型的一次底层升级:不是只提供一个文件入口,而是把文档内容的变化、保存和界面刷新放进更统一的模型里。
重排 API 覆盖更多容器
新版本还改进了 list、grid 和 section 中 item reordering 的 API。这个变化看起来没有 Document 协议那么“架构级”,但对业务 App 很实用。
很多产品都会遇到类似需求:
- 调整任务优先级。
- 拖动卡片改变看板列内顺序。
- 在网格里整理照片、组件或快捷入口。
- 对分组 section 内的内容做局部排序。
如果重排能力只在少数容器里顺手,开发者就会写很多状态同步、索引修正和动画补丁。API 覆盖 list、grid、section 后,SwiftUI 更接近“声明数据顺序,系统负责交互细节”的模型。
展示层:swipe actions、AsyncImage 和懒状态
这次 presentation features 的扩展也很贴近日常开发。
swipe actions on any view 意味着滑动操作不再只绑定在少数列表场景里。比如卡片、消息气泡、搜索结果、收藏项,都可以用更一致的方式暴露“删除、归档、置顶、分享”等动作。
AsyncImage 缓存改进则针对网络图片场景。图片列表、头像墙、商品卡片这类界面,如果缓存行为更好,滚动时的重复请求、闪烁和加载延迟都会更容易控制。
Observable 类型的 lazy state initialization 更偏性能层。它的价值在于:不是所有状态都应该在对象创建时立刻初始化。对昂贵计算、延迟加载数据、按需构造子状态来说,懒初始化可以降低首屏和对象创建成本。
可以这样实践:把新能力拆成可迁移的小步骤
下面的示例不是 WWDC API 的逐字复刻,而是一个可以改造的 SwiftUI 小项目骨架,用来模拟“文档快照 + 可重排列表 + 懒状态”的设计方式。你可以把它作为迁移到新 Document 协议前的代码组织练习。
import SwiftUI
import Observation
struct NoteSnapshot: Identifiable, Codable, Equatable {
var id = UUID()
var title: String
var body: String
}
@Observable
final class NotesModel {
var notes: [NoteSnapshot]
private var cachedWordCount: Int?
init(notes: [NoteSnapshot]) {
self.notes = notes
}
var wordCount: Int {
if let cachedWordCount {
return cachedWordCount
}
let count = notes
.flatMap { ($0.title + " " + $0.body).split(separator: " ") }
.count
cachedWordCount = count
return count
}
func move(from source: IndexSet, to destination: Int) {
notes.move(fromOffsets: source, toOffset: destination)
cachedWordCount = nil
}
func delete(_ note: NoteSnapshot) {
notes.removeAll { $0.id == note.id }
cachedWordCount = nil
}
}
struct NotesView: View {
@State private var model = NotesModel(notes: [
NoteSnapshot(title: "Draft", body: "Sketch the new document flow"),
NoteSnapshot(title: "Review", body: "Check snapshot update boundaries"),
NoteSnapshot(title: "Ship", body: "Measure image and list performance")
])
var body: some View {
NavigationStack {
List {
ForEach(model.notes) { note in
VStack(alignment: .leading) {
Text(note.title).font(.headline)
Text(note.body).font(.subheadline)
}
.swipeActions {
Button(role: .destructive) {
model.delete(note)
} label: {
Label("Delete", systemImage: "trash")
}
}
}
.onMove(perform: model.move)
}
.navigationTitle("Notes · \(model.wordCount) words")
.toolbar { EditButton() }
}
}
}
#Preview {
NotesView()
}
运行方式可以选择新建一个 SwiftUI App,把上面代码放进一个 NotesView.swift,然后在 App 入口里渲染它:
import SwiftUI
@main
struct DemoNotesApp: App {
var body: some Scene {
WindowGroup {
NotesView()
}
}
}
这段代码里有三个可迁移点:
NoteSnapshot把 UI 消费的数据做成明确快照,便于未来接入文档协议。move(from:to:)把重排逻辑集中在 model 中,避免 view 到处改数组。cachedWordCount模拟懒状态:只有 UI 读取时才计算,数据变化时再失效。
采用建议:别一次性重写整个 App
如果你的 App 已经有文档、列表重排和网络图片场景,可以按风险从低到高迁移:
- 先检查
AsyncImage使用点,观察新缓存行为是否能删掉自定义缓存补丁。 - 再把列表、网格、section 的重排逻辑收敛到 model 层,减少 view 内索引操作。
- 对昂贵的
Observable状态做懒初始化,重点看首屏耗时和内存峰值。 - 最后评估新的
Document协议,尤其是保存、撤销、冲突处理和大文件读写路径。
新 SwiftUI 的方向很清楚:让框架接管更多高频交互和状态同步细节。但这不等于所有自定义实现都应该立刻删除。对成熟项目来说,最稳妥的做法是先用性能指标和用户路径定位痛点,再把新 API 用在收益最明显的地方。