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

How can you write copy that attracts users' attention?

Many copywritings written by marketers are often ...

2020 Su Yinhua "Red Dust Thinking" (65 episodes) video

2020 Su Yinhua's "Red Dust Thinking"...

Let’s take a look at a healing story about Siri

What can Siri do? Ask about the weather, ask abou...

After laptops, Sony has made e-books a failure

When it comes to e-books, Sony is the natural pion...

Analysis of Mobike and ofo bike competition

1. Introduction Test models: Xiaomi MAX, iPhone 6...

The most popular marketing copywriting skills in 2020!

If you want to write a popular marketing promotio...