Give your simulator superpowers

RocketSim: An Essential Developer Tool
as recommended by Apple

Win a copy of The macOS App Icon Book with thisfree giveaway

Bar Chart creation using Swift Charts

Apple introduced Swift Charts during WWDC ’22, allowing you to visualize data into bar charts. Before this framework, we had to include all kinds of third-party solutions to draw charts in SwiftUI. Visualizing data using a similar declarative syntax to SwiftUI is simply fantastic.

A bar chart is just one of the available options to visualize your data. In general, many of the methods you’ll learn about today apply to other charts, too. In fact, you could potentially replace a single element to change from a bar to a line chart. Let’s dive in!

Setting up your Chart data

Before we start creating a chart, it’s important to have data to work with. For this article, I’ll use the build activity data I use for RocketSim’s Xcode Build Statistics:

/// Describes an Xcode build activity on a certain data, for a given duration.
struct BuildActivity: Identifiable, Codable {
    var id: TimeInterval { date.timeIntervalSince1970 }
    let date: Date
    let scheme: String
    let numberOfBuilds: Int
}

When starting a new chart, I recommend setting up sample data to work with. You can use this data in both your running app and SwiftUI previews:

extension BuildActivity {
    static func sampleData() -> [BuildActivity] {
        [
            sampleData(for: "RocketSim"),
            sampleData(for: "Stock Analyzer")
        ].flatMap { $0 }
    }
    
    private static func sampleData(for scheme: String) -> [BuildActivity] {
        (0...365).map { index -> BuildActivity in
            /// Create a random number of builds. Some days will not have any builds
            let numberOfBuilds = Int.random(in: 0...100)
            
            /// Using the index, we're creating a full year of data
            let date = Calendar.current.date(byAdding: .day, value: -index, to: .now)!
            
            return BuildActivity(
                date: date,
                scheme: scheme,
                numberOfBuilds: numberOfBuilds
            )
        }
    }
}

These static methods allow you to create a collection of build activities for two different schemes. This data set works great for visualizing a bar chart in this article.

Stay updated with the latest in Swift & SwiftUI

The 2nd largest newsletter in the Apple development community with 19,031 developers. Don't miss out – Join today:

You can always unsubscribe, no hard feelings.

Creating a basic Bar Chart

We can use our sample data to create a basic Bar Chart using Swift Charts in SwiftUI:

A basic example of visualizing your data into graphs using SwiftUI.
A basic example of a Bar Chart using Swift Charts in SwiftUI.

The code for this chart looks as follows:

import SwiftUI
import Charts

struct BarChart: View {
    
    let buildActivities: [BuildActivity]

    var body: some View {
        Chart(buildActivities) { buildActivity in
            BarMark(
                x: .value("Date", buildActivity.date, unit: .day),
                y: .value("Total Count", buildActivity.numberOfBuilds)
            )
        }
    }
}

After importing the Charts framework, we can use the Chart element by passing in our build activities data. The closure requires us to return a data element, for which we will return a bar mark. You can see this as a single bar inside our bar chart.

The x and y values determine how your data will be visualized. We set the date unit to .day since we want to show data for every single day. You could change this value to control the time period of data.

Controlling the chart range of data

While the basic bar chart looks great already, it’s not really useful with a full year of data. You might want to zoom into a single week of data. There are two ways of doing this, each with different results.

The first approach is to use the chartXScale modifier:

/// Chart X scale zoom in, but data is visible out of bounds
.chartXScale(
    domain: startDate...Date.now,
    range: .plotDimension(startPadding: 10, endPadding: 10)
)

By configuring a start date of one week back, we will get the following chart as a result:

The x scale modifier allows you to modify the range of data shown inside a Swift Chart.
The x-scale modifier allows you to modify the range of data shown inside a Swift Chart.

While we can clearly see data for just the last 7 days, it’s not a satisfying result. The bars go out of bounds and our y-scale labels become covered. You could still use this approach as a zoom functionality combined with the chartScrollableAxes modifier, but it’s better to only configure your chart with the data you want to display.

In other words, we will split our data only to contain data for seven days:

BarChart(buildActivities: Array(BuildActivity.sampleData().prefix(7)))

Since our sample data is in reverse order, we can use the prefix modifier to get the first 7 elements. The resulting chart looks much better:

Only provide the data you want to show in a Swift Chart to get the best results.
Only provide the data you want to show in a Swift Chart to get the best results.

How to change the color of a Bar Chart?

The default bar chart color will match the accent color of your app. You can change the color using the foreground style modifier:

Chart(buildActivities) { buildActivity in
    BarMark(
        x: .value("Date", buildActivity.date, unit: .day),
        y: .value("Total Count", buildActivity.numberOfBuilds)
    )
    /// Change the color of bars to orange
    .foregroundStyle(Color.orange)
}

How to split up a bar chart into groups?

Bar charts allow you to split data into groups and visualize them individually. For example, we can split our bar chart based on the given scheme:

You can group a bar chart based on a given value.
You can group a bar chart based on a given value.

You need to provide a specific value that will be used to split up the data. Using a certain category that doesn’t result in too many different groups is recommended. The code for our example looks as follows:

Chart(buildActivities) { buildActivity in
    BarMark(
        x: .value("Date", buildActivity.date, unit: .day),
        y: .value("Total Count", buildActivity.numberOfBuilds)
    )
        /// Show a different color for each scheme
        .foregroundStyle(
            by: .value("Scheme", buildActivity.scheme)
        )
}

Swift Charts will assign a default color to each group. You can override this color by specifying a specific color for each group identifier. In our case, we provide a color for each given scheme:

Chart(buildActivities) { buildActivity in
    BarMark(
        x: .value("Date", buildActivity.date, unit: .day),
        y: .value("Total Count", buildActivity.numberOfBuilds)
    )
        /// Show a different color for each scheme
        .foregroundStyle(
            by: .value("Scheme", buildActivity.scheme)
        )
}
    /// Customize the colors for each scheme
    .chartForegroundStyleScale([
        "RocketSim" : .blue,
        "Stock Analyzer": .red
    ])

Finally, you might want to show the groups side by side. You can do this using the position modifier:

Chart(buildActivities) { buildActivity in
    BarMark(
        x: .value("Date", buildActivity.date, unit: .day),
        y: .value("Total Count", buildActivity.numberOfBuilds)
    )
        /// Show a different color for each scheme
        .foregroundStyle(
            by: .value("Scheme", buildActivity.scheme)
        )
        /// Show bars side by side
        .position(
            by: .value("Scheme", buildActivity.scheme),
            axis: .horizontal,
            span: .ratio(1)
        )
}
    /// Customize the colors for each scheme
    .chartForegroundStyleScale([
        "RocketSim" : .blue,
        "Stock Analyzer": .red
    ])

The axis value controls whether the bars are shown on top of each other (vertical) or next to each other (horizontal). The span allows you to control the width of each individual bar. The resulting bar chart looks as follows:

A bar chart grouped side-by-side with specific colors.
A bar chart grouped side-by-side with specific colors.

Conclusion

Swift Charts make it joyful to visualize data into bar charts. While we’ve only covered the basics in this article, you can already see a fulfilling result. You can customize the color of a bar, group values by a specific category, and control the range of data displayed.

If you want to improve your Swift Charts knowledge even more, check out the SwiftUI category page. Feel free to contact me or tweet me on Twitter if you have any additional tips or feedback.

Thanks!