Adam Rush

@Adam9Rush

6 June, 2022

This article was written using Xcode 14 and iOS 16 Beta 1

Introduction

Apple announced a brand new framework called Swift Charts during the WWDC 22. In this article, we’re going to explore this brand new framework.

Define the Data Source

Before you start building a beautiful looking chart using the Swift Charts framework, you first have to decide what the data source is going to look like. In your example, you’re going to display a chart that represents our SwiftlyRush Bank spend amount per month.

struct Amount: Identifiable {
    var month: String
    var amount: Double
    var id = UUID()
}

You can consider this basic data structure which contains the month and amount of the spend through our digital bank.

var data: [Amount] = [
    .init(month: "March", amount: 100.00),
    .init(month: "April", amount: 200.00),
    .init(month: "May", amount: 120.00)
]

You can go ahead and create a data object which instantiates our data through a tuple, of course, this is a basic example and you might pull this data from a server or similar.

Create the Chart View

You now have the data and the structure, you can go ahead and create a basic bar chart.

import SwiftUI
import Charts

struct BarChart: View {
    
    var data: [Amount] = [
        .init(month: "March", amount: 100.00),
        .init(month: "April", amount: 200.00),
        .init(month: "May", amount: 120.00)
    ]
    
    var body: some View {
        Chart (content: {
            BarMark(
                x: .value("Month", data[0].month),
                y: .value("Total", data[0].amount)
            )
            BarMark(
                 x: .value("Month", data[1].month),
                 y: .value("Total", data[1].amount)
            )
            BarMark(
                 x: .value("Month", data[2].month),
                 y: .value("Total", data[2].amount)
            )
        })
    }
}

Here you are creating the individual BarMark’s separately but we could also iterate over this automatically.

struct BarChart: View {
    
    var data: [Amount] = [
        .init(month: "March", amount: 100.00),
        .init(month: "April", amount: 200.00),
        .init(month: "May", amount: 120.00)
    ]
    
    var body: some View {
        Chart {
            ForEach(data) { item in
                BarMark(
                    x: .value("Month", item.month),
                    y: .value("Total", item.amount)
                )
            }
        }
    }
}

The result is quite remarkable.

You can also use the same data source to define various different chart types.

    var body: some View {
        Chart {
            ForEach(data) { item in
                PointMark(
                    x: .value("Month", item.month),
                    y: .value("Amount", item.amount)
                )
            }
        }
    }

As you can see, you’re now plotting this data instead.

Customizing your Chart

You’re probably wondering if you can change the colour or the Swift Charts and the answer is yes and quite easy too.

struct Amount: Identifiable {
    var month: String
    var amount: Double
    var id = UUID()
    var color: String
}

You have inserted a brand new String item to your data source named “color”.

var data: [Amount] = [
    .init(month: "March", amount: 100.00, color: "red"),
    .init(month: "April", amount: 200.00, color: "green"),
    .init(month: "May", amount: 120.00, color: "yellow")
]

You can go ahead and insert those color choices within your data object.

struct BarChart: View {
    
    var data: [Amount] = [
        .init(month: "March", amount: 100.00, color: "red"),
        .init(month: "April", amount: 200.00, color: "green"),
        .init(month: "May", amount: 120.00, color: "yellow")
    ]
    
    var body: some View {
        Chart {
            ForEach(data) { item in
                BarMark(
                    x: .value("Month", item.month),
                    y: .value("Total", item.amount)
                )
                .foregroundStyle(by: .value("Month Color", item.color))
            }
        }
    }
}

You can insert a foregroundStyle modifier with the value of the colour, and watch the result.

Expand the Data Source

Let’s go ahead and expand our data source to contain more data points.

    enum Month: String, CaseIterable {
        case January
        case Febuary
        case March
        case April
        case May
        case June
    }
    
    private func randomMonth() -> String {
        return Month.allCases.randomElement()?.rawValue ?? ""
    }
    
    private func generateData() -> [Amount] {
        var array: [Amount] = []
        for _ in 0...50 {
            array.append(Amount(month: randomMonth(), amount: Double.random(in: 1...1000)))
        }
        return array
    }

Let’s go ahead and insert the above boilerplate code that will create some dummy data for us to use on the Swift Charts. You’re creating an enum that will contain our Months of the year.

You’re then creating a function which will return a String of a random Month case.

Finally, you’re generating an array of 50 items that will be plotted on the chart.

var body: some View {
    Chart {
        ForEach(generateData()) { item in
            PointMark(
                x: .value("Month", item.month),
                y: .value("Amount", item.amount)
            )
        }
    }
}

The final piece is to insert the generateData() function inside our data ForEach loop.

Build & Run the project.

You can also go a step further and remove the ForEach and pass the data directly to the Chart.

var body: some View {
    Chart(generateData()) { item in
        BarMark(
            x: .value("Month", item.month),
            y: .value("Amount", item.amount)
        )
    }
}

What Next?

This article is a living document and will be continuously updated throughout the week. You can read more about Swift Charts here.

You can read more about all the WWDC changes right here.

Sponsor

Subscribe for curated Swift content for free

- weekly delivered.