认识 Swift Charts
Hello Swift Charts
2022年6月6日
一句话判断
Swift Charts 是今年 SwiftUI 生态中最实用的新增框架——如果你需要在应用里展示数据图表,直接用它就够了。
这场 Session 讲了什么
Swift Charts 是 Apple 全新的声明式图表框架,完全基于 SwiftUI 语法构建。Session 用一个煎饼食品追踪应用的示例,从零开始展示了三种图表的构建过程:
柱状图:展示不同煎饼品种的销量对比。使用 BarMark 配合 ForEach 遍历数据数组。交换 x 和 y 值可以轻松转置为横向柱状图。
多系列柱状图:对比两个城市(Cupertino 和 San Francisco)的每日销量。通过 SwiftUI Picker 切换城市,配合 .animation(.easeInOut) 实现平滑的柱状图过渡动画。
多系列折线图:将两个城市的数据同时展示在一张图中。使用 LineMark 配合 .foregroundStyle(by:) 区分不同系列,PointMark 标注数据点。
Swift Charts 的核心设计理念是”Mark”(标记)——每种图表类型对应一种 Mark(BarMark、LineMark、PointMark 等)。你通过组合不同的 Mark 来构建图表,就像在 SwiftUI 中组合 View 一样。
值得深挖的点
无障碍访问的深度集成是 Swift Charts 的一大亮点。图表数据自动暴露给 VoiceOver,用户可以通过语音导航逐项浏览数据。更酷的是 Audio Graphs——系统可以将图表数据转化为音调变化,用户通过听觉就能感知数据趋势。这两个功能不需要额外代码,Swift Charts 自动处理。
自动适配的轴和标签减少了大量手动调整工作。Swift Charts 根据数据类型自动选择合适的轴样式——日期数据用时间轴,数值数据用线性轴,分类数据用离散轴。深色模式、动态字体、不同设备尺寸都自动适配。
声明式语法的表达力在这里体现得很好。一个 foregroundStyle(by: .value("City", series.city)) 就能自动为不同系列分配颜色和图例。不需要手动管理颜色映射和图例布局。
代码片段
基础柱状图:
struct PancakeSales: Identifiable {
let name: String
let sales: Int
var id: String { name }
}
let data = [
PancakeSales(name: "Cachapa", sales: 916),
PancakeSales(name: "Injera", sales: 850),
PancakeSales(name: "Crêpe", sales: 802),
]
Chart(data) { element in
BarMark(
x: .value("销量", element.sales),
y: .value("品种", element.name)
)
}
.chartYAxisLabel("煎饼销量")
多系列折线图:
Chart(seriesData) { series in
ForEach(series.salesData) { data in
LineMark(
x: .value("日期", data.date, unit: .day),
y: .value("销量", data.sales)
)
.foregroundStyle(by: .value("城市", series.city))
PointMark(
x: .value("日期", data.date, unit: .day),
y: .value("销量", data.sales)
)
.foregroundStyle(by: .value("城市", series.city))
}
}
// 动画过渡
.animation(.easeInOut)
带城市切换的交互式图表:
@State var city: City = .cupertino
Picker("城市", selection: $city) {
Text("Cupertino").tag(City.cupertino)
Text("San Francisco").tag(City.sf)
}
.pickerStyle(.segmented)
Chart {
let data = city == .cupertino ? cupertinoData : sfData
ForEach(data) { element in
BarMark(
x: .value("日期", element.date, unit: .day),
y: .value("销量", element.sales)
)
}
}
最佳实践
- 数据结构遵循 Identifiable:让 ForEach 和 Chart 初始化器直接接受数据集合
- 用
.value()而非直接设值:.value("描述", 实际值)让框架生成正确的轴标签和无障碍描述 - 横向标签空间不够就转置:交换 x 和 y 即可,不用手动调布局
- 利用 SwiftUI 动画:数据切换时
.animation()让图表过渡流畅自然 - 组合多种 Mark:LineMark + PointMark 是常见搭配,折线加数据点可读性更好
还有什么值得关注
- Swift Charts 支持 AreaMark(面积图)、RectangleMark(矩形图)等多种 Mark 类型
- 图表自动支持 VoiceOver 和 Audio Graphs,无需额外代码
- Dark Mode 和 Dynamic Type 自动适配,Xcode 的 variant 功能可以预览不同外观
- 框架的设计思路和 SwiftUI 一脉相承,学习曲线非常平缓