Highlight
Swift Charts 是 Apple 在 WWDC 2022 发布的声明式图表框架,完全基于 SwiftUI 语法。它用 Mark(标记)的概念统一了所有图表类型——BarMark、LineMark、PointMark 等——你通过组合这些 Mark 来构建图表,就像在 SwiftUI 中组合 View 一样。Session 用一个煎饼销量追踪 App,从零展示了柱状图、多系列对比图和组合图表的构建过程。
核心内容
Swift Charts 解决了一个长期存在的问题:在 Apple 平台上做数据可视化,要么用第三方库,要么自己画 Core Graphics。这两个选项都很重。
新的 Swift Charts 框架带来了声明式图表语法。你只需要描述数据映射关系——“x 轴是日期,y 轴是销量”——框架自动处理坐标轴、刻度、图例和交互。
Session 中用一个 Pancake Food Truck 应用演示了三种典型场景。这个 App 记录 Cupertino 和 San Francisco 两个城市不同煎饼品种的销量数据。
第一个场景是柱状图,展示各品种总销量排名。代码很简单:
Chart(panSales) {
BarMark(
x: .value("Pancake", $0.type),
y: .value("Sales", $0.sales)
)
}
这里的 .value() 方法很关键——第一个参数是标签描述,第二个参数是实际值。框架用这个描述来生成轴标签和无障碍 VoiceOver 描述,而不只是显示原始数值。
第二个场景是多系列对比。应用中加入了城市选择器,用 SwiftUI Picker 切换 Cupertino 和 San Francisco 的数据。加一行 .foregroundStyle(by: .value("City", $0.city)) 就能按城市着色区分。
第三个场景是组合图表,把两个城市的数据叠在同一张图里。LineMark 画折线,PointMark 标注数据点,.foregroundStyle(by:) 自动分配颜色和生成图例。
详细内容
BarMark:柱状图的基础
Swift Charts 的核心理念是 Mark。每种图表类型对应一种 Mark,就像 SwiftUI 中每种 UI 元素对应一种 View。
BarMark 是最基础的 Mark,用来创建柱状图。初始化需要 x 和 y 两个维度:
Chart(salesData) { sale in
BarMark(
x: .value("品种", sale.pancakeType),
y: .value("销量", sale.count)
)
}
Chart 构造器接受一个 RandomAccessCollection,数组中的每个元素对应图表上的一个数据点。如果你的数据遵循 Identifiable,可以直接传入集合。
想让柱状图变成横向?交换 x 和 y 的值即可:
BarMark(
x: .value("销量", sale.count),
y: .value("品种", sale.pancakeType)
)
框架自动调整轴标签方向和布局,不需要手动计算 frame 或旋转视图。
多系列与动态数据
当图表包含多个数据系列时,.foregroundStyle(by:) 是关键 modifier:
Chart(salesByCity) { sale in
BarMark(
x: .value("日期", sale.date, unit: .day),
y: .value("销量", sale.count)
)
.foregroundStyle(by: .value("城市", sale.city))
}
框架自动为每个城市分配颜色、生成图例。配合 SwiftUI 的 .animation() 可以让数据切换时图表平滑过渡:
Chart(filteredSales) { ... }
.animation(.easeInOut, value: selectedCity)
这段代码的意思是:当 selectedCity 变化导致数据过滤结果改变时,图表以 easeInOut 曲线动画过渡到新状态。
LineMark 和 PointMark 的组合
折线图使用 LineMark,和 BarMark 语法几乎一致:
Chart(salesByDate) { sale in
LineMark(
x: .value("日期", sale.date),
y: .value("销量", sale.count)
)
.foregroundStyle(by: .value("城市", sale.city))
}
加上 PointMark 可以在折线的每个数据点上显示标记:
Chart(salesByDate) { sale in
LineMark(
x: .value("日期", sale.date),
y: .value("销量", sale.count)
)
.foregroundStyle(by: .value("城市", sale.city))
PointMark(
x: .value("日期", sale.date),
y: .value("销量", sale.count)
)
.foregroundStyle(by: .value("城市", sale.city))
}
这种组合模式是 Swift Charts 设计的关键——不同 Mark 可以自由叠加,框架统一处理坐标映射。
其他图表类型
Session 最后快速展示了 Swift Charts 支持的其他 Mark 类型:
// 面积图
AreaMark(
x: .value("日期", data.date),
y: .value("值", data.value)
)
// 规则线(阈值线)
RuleMark(
y: .value("目标", targetValue)
)
// 矩形(热力图)
RectangleMark(
x: .value("列", data.col),
y: .value("行", data.row)
)
每种 Mark 的 API 都遵循相同的模式:x 和 y 维度用 .value() 描述映射关系,数据通过 Chart 初始化器传入。
核心启发
- Mark 组合模式是框架的灵魂:不把图表看作固定模板(柱状图/折线图/饼图),而是看作 Mark 的组合。LineMark + PointMark 是常见搭配,AreaMark + LineMark 也可以叠加。这种设计让自定义图表变得自然,不用学另一套 DSL。
.value()不只是设值,是为无障碍和轴标签提供语义:第一个参数会被 VoiceOver 朗读、被轴标签引用。写.value("销量", count)而不仅仅是传 count,这个习惯值得从一开始就养成。- 数据驱动动画几乎零成本:用
.animation(.easeInOut, value: selectedCity)一行代码就能让图表数据切换时平滑过渡。这是 SwiftUI 声明式范式在图表领域的自然延伸——你声明数据变化,框架负责动画。 - 转置图表不需要改数据,交换 x/y 就行:横向柱状图、纵向柱状图的切换只是
BarMark(x:y:)两个参数的顺序问题。框架自动处理坐标轴方向、标签位置和布局。 Identifiable数据模型让代码更简洁:让数据 struct 遵循Identifiable,Chart可以直接用数组初始化,ForEach也不需要指定 id。这是 SwiftUI 数据流的最佳实践在 Charts 中的延续。
关联 Session
- The SwiftUI cookbook for navigation — get the recipes you need to build a great navigation experience for your app, using the new navigation apis introduced in swiftui.
- What’s new in SwiftUI — an overview of the latest swiftui features announced at wwdc22. we’ll explore swift charts, navigation apis, layout enhancements, and much more.
- Use SwiftUI with UIKit — learn how you can use swiftui and uikit together to build a great experience in your app.
- Design an effective chart — discover how you can create a clear, understandable chart that helps people make decisions.
- Build a productivity app for Apple Watch — learn how you can build a productivity app that is quick and lightweight.
评论
GitHub Issues · utterances