Highlight
SwiftUI 在 WWDC 2022 中新增 Swift Charts、NavigationStack、NavigationSplitView、Layout 协议、Grid、ShareLink、PhotosPicker、Transferable 和多项控件更新,覆盖图表、导航、布局、分享和跨平台交互。
核心内容
SwiftUI 早期常见的麻烦,是简单界面很快,复杂应用会碰到几类缺口:图表要找第三方库,导航状态难以持久化,自定义布局依赖 GeometryReader,分享、拖拽、照片选择需要跨框架拼接。
2022 年的 SwiftUI 更新集中补这些缺口。Apple 用声明式 API 把图表、导航、布局、分享和数据传输放进同一套模型。开发者写的仍然是 view 和 modifier,但覆盖的应用结构更完整。
本场演讲用一个 Party Planner 示例串起更新:用 Swift Charts 展示待办进度,用新的导航 API 组织层级,用 Grid 和 Layout 处理自定义排布,用 PhotosPicker、ShareLink 和 Transferable 处理照片、分享和拖拽。
详细内容
Swift Charts
(02:51)Swift Charts 用 Chart 容器和 mark 类型描述图表。BarMark、LineMark、RuleMark 等 mark 与 SwiftUI modifier 配合,系统处理本地化、Dynamic Type、Dark Mode 和可访问性。
Chart(tasks) { task in
BarMark(
x: .value("Task", task.name),
y: .value("Remaining", task.remainingCount)
)
.foregroundStyle(by: .value("Category", task.category))
}
关键点:
Chart(tasks)遍历模型集合生成图表BarMark声明柱状图的单个 markx和y使用.value绑定语义标签和数据foregroundStyle(by:)按类别自动生成颜色编码
数据驱动导航
(10:27)NavigationStack 替代传统 stack 导航。开发者用 value-based NavigationLink 表示目的地,用 navigationDestination 注册值到视图的映射。导航路径可以保存在数组中,适合恢复状态或一键回到根页面。
NavigationStack(path: $path) {
List(tasks) { task in
NavigationLink(value: task) {
Text(task.name)
}
}
.navigationDestination(for: PartyTask.self) { task in
TaskDetail(task: task)
}
}
关键点:
path保存当前导航栈状态NavigationLink(value:)传递模型值,不直接构造目标视图navigationDestination统一定义某类值对应的页面- 修改
path数组即可控制 push、pop 和恢复
自定义布局
(22:02)Layout 协议让自定义布局成为 SwiftUI 的一等能力。过去常用 GeometryReader 手动测量,现在布局可以实现测量和摆放逻辑,并保留动画能力。
struct RadialLayout: Layout {
func sizeThatFits(proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) -> CGSize {
proposal.replacingUnspecifiedDimensions()
}
func placeSubviews(in bounds: CGRect,
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) {
for (index, subview) in subviews.enumerated() {
let angle = Angle.degrees(Double(index) / Double(subviews.count) * 360)
let point = CGPoint(x: bounds.midX + cos(angle.radians) * 120,
y: bounds.midY + sin(angle.radians) * 120)
subview.place(at: point, anchor: .center, proposal: .unspecified)
}
}
}
关键点:
Layout分离测量和摆放sizeThatFits返回容器需要的尺寸placeSubviews决定每个子视图的位置subview.place由布局系统执行最终摆放
分享与传输
(24:45)PhotosPicker 提供 SwiftUI 原生照片选择器。用户选择图片后,示例代码通过 loadTransferable(type: Image.self) 将 PhotosPickerItem 加载为 SwiftUI Image。
@Published var imageSelection: PhotosPickerItem? = nil {
didSet {
if let imageSelection = imageSelection {
let progress = loadTransferable(from: imageSelection)
imageState = .loading(progress)
} else {
imageState = .empty
}
}
}
private func loadTransferable(from imageSelection: PhotosPickerItem) -> Progress {
return imageSelection.loadTransferable(type: Image.self) { result in
DispatchQueue.main.async {
guard imageSelection == self.imageSelection else { return }
switch result {
case .success(let image?):
self.imageState = .success(image)
case .success(nil):
self.imageState = .empty
case .failure(let error):
self.imageState = .failure(error)
}
}
}
}
关键点:
imageSelection保存用户在PhotosPicker中选择的PhotosPickerItemdidSet在选择变化时启动加载,并先把状态切到.loading(progress)loadTransferable(type: Image.self)使用系统传输机制把选择项加载为Imageguard imageSelection == self.imageSelection避免旧的异步结果覆盖新的选择success、nil和failure分支分别更新成功、空状态和错误状态
(25:51)处理后的图片可以直接交给 ShareLink 分享。演讲还展示了 .dropDestination(payloadType: Image.self),同一类 Image 数据可用于拖拽接收。
if let item = viewModel.processedImage {
ShareLink(
item: item, preview: SharePreview("Birthday Effects"))
}
关键点:
processedImage存在时才显示分享入口ShareLink接收要分享的itemSharePreview设置系统分享面板中的预览标题- 这里使用 session 代码中的
Image,不扩展示例中没有出现的自定义Transferable实现
核心启发
-
把运营看板改成原生 Swift Charts:用
Chart、BarMark、LineMark展示销售、习惯打卡或项目进度。系统自动处理无障碍和主题适配,适合替换轻量第三方图表库。 -
让导航状态可保存:用
NavigationStack(path:)管理详情页路径。用户重启应用后恢复到上次打开的项目详情,或在深链中直接构造路径进入多级页面。 -
用 Layout 做品牌化排版:为照片墙、仪表盘、课程进度做自定义布局。实现
Layout后,布局可以参与 SwiftUI 动画,不需要 GeometryReader 拼坐标。 -
用 Transferable 统一分享和拖拽:让卡片、图片、笔记条目实现
Transferable。同一份数据模型同时支持 ShareLink、拖拽到其他 App、复制粘贴。
关联 Session
- The SwiftUI cookbook for navigation — 深入讲解 NavigationStack 和 NavigationSplitView
- Compose custom layouts with SwiftUI — 使用 Layout 协议构建自定义布局
- SwiftUI on iPad: Organize your interface — SwiftUI 在 iPad 上的列表、表格和选择
- Bring multiple windows to your SwiftUI app — 为 SwiftUI 应用添加多窗口能力
评论
GitHub Issues · utterances