Creating a Line Chart with SwiftUI Charts in iOS 16

Creating a Line Chart with SwiftUI Charts in iOS 16

Preface

Apple introduced SwiftUI Charts at WWWDC 2022, which makes it incredibly easy to create charts in SwiftUI views. Charts are a great way to present visual data in a rich format that is easy to understand. This article shows how to easily create a line chart with much less code than you would have to create the same line chart from scratch before. It's also very easy to customize the look and feel of the chart and make the information in the chart easily accessible.

As shown in previous articles, it’s possible to create a line chart without using SwiftUI Charts. However, using the Charts[1] framework makes it much easier by providing a wide range of charts to explore the most effective approach to the data in your app.

Series of articles

  1. How to create a bar chart in SwiftUI
  2. Horizontal Bar Chart in SwiftUI
  3. Customizing a Line Chart with SwiftUI Charts in iOS 16
  4. Using the Foudation library's measurement types in Swift charts

Simple line chart

Start with data that contains step counts for a week, similar to the data used in Create a line chart in SwiftUI. Define a structure to hold the date and the number of steps for that day, and create an array for the current week.

 struct StepCount : Identifiable {
let id = UUID ( )
let weekday : Date
let steps : Int
init ( day : String , steps : Int ) {
let formatter = DateFormatter ( )
formatter .dateFormat = "yyyyMMdd"
self .weekday = formatter .date ( from : day ) ? ? Date .distantPast
self .steps = steps
}
}
let currentWeek : [ StepCount ] = [
StepCount ( day : "20220717" , steps : 4200 ) ,
StepCount ( day : "20220718" , steps : 15000 ) ,
StepCount ( day : "20220719" , steps : 2800 ) ,
StepCount ( day : "20220720" , steps : 10800 ) ,
StepCount ( day : "20220721" , steps : 5300 ) ,
StepCount ( day : "20220722" , steps : 10400 ) ,
StepCount ( day : "20220723" , steps : 4000 )
]

To create a line chart, create a chart with a LineMark for each element in the step data. Specify the weekday in the X value of the LineMark and the number of steps in the Y value. Note that you also need to import the Charts framework.

This creates a line chart for the step data. Since there is only one series of data, the ForEach can be omitted and the data can be passed directly to the Chart initializer. Both parts produce the same line chart.

 import SwiftUI
import Charts
struct LineChart1 : View {
var body : some View {
VStack {
GroupBox ( "Line Chart - Step Count" ) {
Chart {
ForEach ( currentWeek ) {
LineMark (
x : .value ( "Week Day" , $0 .weekday , unit : .day ) ,
y : .value ( "Step Count" , $0 .steps )
)
}
}
}
GroupBox ( "Line Chart - Step Count" ) {
Chart ( currentWeek ) {
LineMark (
x : .value ( "Week Day" , $0 .weekday , unit : .day ) ,
y : .value ( "Step Count" , $0 .steps )
)

}
}
}
}
}

A line chart showing daily step count created using SwiftUI Charts

Other charts

SwiftUI Charts has many chart options available. These can be used to generate bar charts by changing the chart marker from LineMark to other types of markers such as BarMark.

 struct OtherCharts : View {
var body : some View {
VStack {
GroupBox ( "Line Chart - Step count" ) {
Chart ( currentWeek ) {
LineMark (
x : .value ( "Week Day" , $0 .weekday , unit : .day ) ,
y : .value ( "Step Count" , $0 .steps )
)
}
}
GroupBox ( "Bar Chart - Step count" ) {
Chart ( currentWeek ) {
BarMark
x : .value ( "Week Day" , $0 .weekday , unit : .day ) ,
y : .value ( "Step Count" , $0 .steps )
)
}
}
GroupBox ( "Point Chart - Step count" ) {
Chart ( currentWeek ) {
PointMark (
x : .value ( "Week Day" , $0 .weekday , unit : .day ) ,
y : .value ( "Step Count" , $0 .steps )
)
}
}
GroupBox ( "Rectangle Chart - Step count" ) {
Chart ( currentWeek ) {
RectangleMark (
x : .value ( "Week Day" , $0 .weekday , unit : .day ) ,
y : .value ( "Step Count" , $0 .steps )
)
}
}
GroupBox ( "Area Chart - Step count" ) {
Chart ( currentWeek ) {
AreaMark (
x : .value ( "Week Day" , $0 .weekday , unit : .day ) ,
y : .value ( "Step Count" , $0 .steps )
)
}
}
}
}
}

Other chart types created with SwiftUI Charts, showing daily step count

Making line charts more accessible

One benefit of building the chart into SwiftUI is that it’s easy to make the chart accessible using accessibility modifiers [2]. Add a computed property for StepCount that returns the data as a string that can be used by accessibilityLabel. Then add accessibility labels and values ​​for each marker in the chart.

 struct StepCount : Identifiable {
let id = UUID ( )
let weekday : Date
let steps : Int
init ( day : String , steps : Int ) {
let formatter = DateFormatter ( )
formatter .dateFormat = "yyyyMMdd"
self .weekday = formatter .date ( from : day ) ? ? Date .distantPast
self .steps = steps
}
var weekdayString : String {
let dateFormatter = DateFormatter ( )
dateFormatter .dateFormat = "yyyyMMdd"
dateFormatter .dateStyle = .long
dateFormatter .timeStyle = .none
dateFormatter .locale = Locale ( identifier : "en_US" )
return dateFormatter .string ( from : weekday )
}
}
 GroupBox ( "Line Chart - Daily Step Count" ) {
Chart ( currentWeek ) {
LineMark (
x : .value ( "Week Day" , $0 .weekday , unit : .day ) ,
y : .value ( "Step Count" , $0 .steps )
)
.accessibilityLabel ( $0 .weekdayString )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
}

Making Line Charts Accessible in SwiftUI Charts

Add multiple data series to a line chart

A line chart is a great way to compare two different series of data. Create a second series, the number of steps from the previous week, and add both series to the line chart.

 let previousWeek : [ StepCount ] = [
StepCount ( day : "20220710" , steps : 15800 ) ,
StepCount ( day : "20220711" , steps : 7300 ) ,
StepCount ( day : "20220712" , steps : 8200 ) ,
StepCount ( day : "20220713" , steps : 25600 ) ,
StepCount ( day : "20220714" , steps : 16100 ) ,
StepCount ( day : "20220715" , steps : 16500 ) ,
StepCount ( day : "20220716" , steps : 3200 )
]
let currentWeek : [ StepCount ] = [
StepCount ( day : "20220717" , steps : 4200 ) ,
StepCount ( day : "20220718" , steps : 15000 ) ,
StepCount ( day : "20220719" , steps : 2800 ) ,
StepCount ( day : "20220720" , steps : 10800 ) ,
StepCount ( day : "20220721" , steps : 5300 ) ,
StepCount ( day : "20220722" , steps : 10400 ) ,
StepCount ( day : "20220723" , steps : 4000 )
]
let stepData = [
( period : "Current Week" , data : currentWeek ) ,
( period : "Previous Week" , data : previousWeek )
]

The first attempt to add the data for these two series did not display as expected.

 struct LineChart2 : View {
var body : some View {
GroupBox ( "Line Chart - Daily Step Count" ) {
Chart {
ForEach ( stepData , id : \ .period ) {
ForEach ( $ 0.data ) {
LineMark (
x : .value ( "Week Day" , $0 .weekday , unit : .day ) ,
y : .value ( "Step Count" , $0 .steps )
)
.accessibilityLabel ( $0 .weekdayString )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
}
}
}
}
}

First attempt at creating a line chart with two series of step data in SwiftUI Charts

Display step series

Display multiple weekday-based step count series in a line chart

The problem with my initial attempt to display multiple sets of data in a line chart was that the X-axis used dates. The current week number followed the previous week, so each point was plotted linearly along the X-axis.

It is necessary to use only weekdays as the x-axis values, so that all Sundays are plotted on the same x-coordinate.

Add another calculated property to StepCount to return the short day of the weekday in string format.

 struct StepCount : Identifiable {
. . .
var shortDay : String {
let dateFormatter = DateFormatter ( )
dateFormatter .dateFormat = "EEE"
return dateFormatter .string ( from : weekday )
}
}

This shortDay is used for the x-values ​​of the LineMarks in the chart. Additionally, the foreground is styled as a period based on the stepCount array. The line chart uses the weekdays on the x-axis to show the number of steps for two weeks, allowing comparisons between weeks.

 struct LineChart3 : View {
var body : some View {
VStack {
GroupBox ( "Line Chart - Daily Step Count" ) {
Chart {
ForEach ( stepData , id : \ .period ) { steps in
ForEach ( steps .data ) {
LineMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.foregroundStyle ( by : .value ( "Week" , steps .period ) )
.accessibilityLabel ( $0 .weekdayString )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
}
}
.frame ( height : 400 )
}
.padding ( )

Spacer ( )
}
}
}

Line chart with two series of step data in SwiftUI Charts

in conclusion

There’s a lot more to explore in SwiftUI Charts. Using this framework is definitely better than building your own charts from scratch.

References

[1] Charts: https://developer.apple.com/documentation/charts.​​

[2] Accessibility modifiers: https://developer.apple.com/documentation/swiftui/view-accessibility.

<<:  Let's talk about the three new font width styles in iOS 16

>>:  Solution to resource confusion in Android plug-in

Recommend

Learn these 5 operational thinking from Zhang Xiaolong’s public speeches

At the WeChat Leadership Conference that just end...

The Chinese dragon once had wings

"Cloud Dragon", by Chen Rong, Song Dyna...

The "Deposit phone bill and get a free phone" benefit is still available

In August this year, the media widely circulated ...

Keep your apps away from jailbreak: iOS 14 App Attest protection feature

When jailbreaking first became popular on iOS dev...

Master these 4 points! Tik Tok search traffic is easily captured!

Do a little survey! If you were born after 85s, 9...

How to formulate operation strategies based on user life cycle?

I believe that many of my friends have read a lot...

How can we have high-quality sleep?

"Apply the most expensive facial mask and st...

Lilies from southwest China bloom in botanical gardens around the world

Glaciers, snow-capped peaks, streams, and river v...

Where did the traffic of Viya and Xue Li go?

1.341 billion yuan is the amount of money that th...

How to choose the right shoes for running?

When running, a good pair of sports shoes is very...