Swift and SwiftUI tutorials for Swift Developers

Swift Charts with SwiftUI

In the current mobile development ecosystem, data visualization is not a luxury; it is a necessity. Whether you are building a fitness app for watchOS, a financial dashboard for iPadOS, or an analytics tool for macOS, the ability to represent data visually and comprehensively is fundamental.

If you are an iOS developer who has been struggling with complex third-party libraries or drawing manually with CoreGraphics for a while, I have good news: the Swift Charts framework in SwiftUI has arrived to change the game.

In this Swift programming tutorial, we will break down everything from basic concepts to advanced techniques for implementing native, accessible, and animated charts using Swift, SwiftUI, and Xcode.


What is Swift Charts?

Introduced at WWDC22, Swift Charts is a declarative framework designed by Apple that allows you to generate visually striking charts with very little code. Unlike older imperative solutions, Swift Charts adopts the SwiftUI philosophy: you describe what you want to show, and the framework takes care of how to render it.

For an iOS developer, this means:

  • Declarative Syntax: You use familiar structures like ViewBuilder.
  • Adaptability: It looks perfect on iOS, macOS, and watchOS automatically.
  • Native Accessibility: Automatic support for VoiceOver and Audio Graphs.
  • Animations: Seamless integration with SwiftUI’s animation system.

Setting up the Environment in Xcode

To start working with Swift Charts in SwiftUI, you need to ensure you have the right tools.

  • Xcode: Version 14.0 or higher (Xcode 15+ is recommended for the latest interactivity features).
  • Target: iOS 16.0+, macOS 13.0+, watchOS 9.0+, tvOS 16.0+.

Open Xcode, create a new project, and make sure to import the framework in your files:

import SwiftUI
import Charts

If you don’t import Charts, the compiler won’t recognize components like Chart, BarMark, or LineMark.


Fundamental Concepts: Your First Chart

The architecture of Swift Charts is based on composition. A chart is essentially a container (Chart) that groups a series of marks (Marks). A “Mark” is the visual representation of a data point: a bar, a dot, a line, etc.

1. Preparing the Data

In modern Swift programming, strong typing is your friend. Let’s define a simple data model to visualize views for a tech blog.

struct ViewCount: Identifiable {
    let id = UUID()
    let category: String
    let views: Int
}

let data: [ViewCount] = [
    .init(category: "SwiftUI", views: 4500),
    .init(category: "UIKit", views: 2300),
    .init(category: "CoreData", views: 1500),
    .init(category: "Metal", views: 800)
]

2. Creating a BarMark (Bar Chart)

The most common chart is the bar chart. Let’s see how to transform our data array into a visualization.

struct BlogViewsChart: View {
    var body: some View {
        VStack {
            Text("Views by Category")
                .font(.title2)
                .bold()
            
            Chart(data) { item in
                BarMark(
                    x: .value("Category", item.category),
                    y: .value("Views", item.views)
                )
                .foregroundStyle(.blue.gradient)
            }
            .frame(height: 300)
            .padding()
        }
    }
}

Code Analysis:

  • Chart(data): We initialize the chart by passing our array. It acts like a ForEach loop.
  • BarMark: Defines that we want bars.
  • PlottableValue: The x and y parameters expect a .value. The first argument is the label (for accessibility), and the second is the actual data.
  • .foregroundStyle: Standard SwiftUI modifier to apply styling.

Exploring Mark Types

As an iOS developer, you must know how to choose the right visualization for your data. Swift Charts offers a wide variety of marks. Changing the chart type is as simple as changing the mark’s name.

LineMark and PointMark (Line and Scatter Charts)

Ideal for viewing trends over time.

struct TrendChart: View {
    // Assume a 'DailyData' model with date and value
    let dailyData: [DailyData] 
    
    var body: some View {
        Chart(dailyData) { item in
            LineMark(
                x: .value("Date", item.date),
                y: .value("Users", item.users)
            )
            .interpolationMethod(.catmullRom) // Smooths the line
            
            // Composition: Add points on top of the line
            PointMark(
                x: .value("Date", item.date),
                y: .value("Users", item.users)
            )
            .foregroundStyle(.red)
        }
    }
}

This capability for composition (placing a PointMark on top of a LineMark) is where Swift Charts in SwiftUI shines. You don’t need complex layer configurations; you simply stack the views inside the Chart block.

AreaMark (Area Chart)

Useful for showing volumes or accumulations.

AreaMark(
    x: .value("Date", item.date),
    y: .value("Sales", item.sales)
)
.foregroundStyle(.indigo.opacity(0.4))

RuleMark (Rules and Guides)

We often need a horizontal or vertical line to mark a goal or an average.

RuleMark(
    y: .value("Goal", 3000)
)
.lineStyle(StrokeStyle(lineWidth: 2, dash: [5]))
.annotation(position: .leading) {
    Text("Monthly Target")
        .font(.caption)
        .foregroundColor(.secondary)
}

Advanced Customization and Styling

A good iOS developer doesn’t settle for defaults. Xcode and SwiftUI allow us to customize every aspect of the axes and legends.

Axis Customization (XAxis and YAxis)

By default, Swift Charts decides how to display labels. We can override this using the .chartXAxis and .chartYAxis modifiers.

Chart(data) { item in
    BarMark(...)
}
.chartXAxis {
    AxisMarks(values: .automatic) { _ in
        AxisGridLine()
        AxisTick()
        AxisValueLabel()
            .foregroundStyle(.gray)
    }
}
.chartYAxis {
    // Hide Y axis completely
    AxisMarks(position: .leading)
}

Scales and Domains

If you want your chart to always start at 0, or have a specific range (e.g., 0 to 100%), use .chartYScale.

.chartYScale(domain: 0...100)

Color and Categorization

To visually group data, you can use the .foregroundStyle modifier mapped to a data value.

BarMark(...)
    .foregroundStyle(by: .value("Type", item.type))

This will automatically generate a legend at the bottom of the chart.


Interactivity: The New Standard in iOS 17

Before iOS 17, interactivity in Swift Charts was a bit complex (requiring ChartProxy and GeometryReader). Now, with recent Swift updates, it is much more intuitive.

To create a chart where the user can select a point and see details (“Scrubbing”), we use the .chartXSelection modifier.

Selection Implementation

struct InteractiveChart: View {
    @State private var selectedDate: Date?
    var data: [DailyData]

    var body: some View {
        Chart(data) { item in
            LineMark(
                x: .value("Date", item.date),
                y: .value("Value", item.value)
            )
            
            if let selectedDate, let item = findItem(for: selectedDate) {
                // Draw a vertical line where the user touches
                RuleMark(x: .value("Selection", selectedDate))
                    .foregroundStyle(.gray.opacity(0.5))
                    .annotation(position: .top) {
                        Text("\(item.value)")
                            .font(.headline)
                            .padding(4)
                            .background(.regularMaterial, in: RoundedRectangle(cornerRadius: 8))
                    }
            }
        }
        // Enable selection via gesture
        .chartXSelection(value: $selectedDate)
    }
    
    // Helper function to find the closest data point
    func findItem(for date: Date) -> DailyData? {
        // Logic to search 'data' array for element closest to 'date'
        return data.first { $0.date == date } // Simplified
    }
}

This code allows the user to slide their finger over the chart and see a real-time update. It’s a top-tier User Experience (UX) expected from any professional app on the App Store.


Optimization for Google and the Apple Ecosystem

As a developer, you don’t just write code, you build products. Here are key tips for integrating this into a professional environment:

1. Performance

Although SwiftUI is fast, rendering thousands of points can be expensive.

  • Filter your data before passing it to the chart. Don’t try to plot 10,000 points on an iPhone screen. Aggregate the data (e.g., weekly averages instead of per-second data).
  • Use .animation(.easeInOut, value: data) carefully. Animating large datasets can cause dropped frames.

2. Accessibility (A11y)

Swift Charts automatically generates accessibility trees. However, you can improve them.

  • Use .accessibilityLabel and .accessibilityValue if the visual data isn’t enough.
  • Apple’s Audio Graphs feature allows blind users to “hear” the chart trend (high pitches for high values, low for low). This comes “for free” when using the native framework, something third-party libraries rarely offer.

3. Multiplatform Adaptability

The same code works on macOS and watchOS.

  • On watchOS: Simplify the chart. Remove legends and reduce the number of axis labels.
  • On macOS: Take advantage of the space. Add more annotations and details. Mouse hover is handled just like touch on iOS thanks to SwiftUI abstraction.

Integrating Swift Charts into MVVM Architectures

For a senior iOS developer, spaghetti code in the View is unacceptable. Swift Charts in SwiftUI integrates perfectly with the MVVM pattern.

class ChartViewModel: ObservableObject {
    @Published var data: [SalesData] = []
    
    func fetchData() {
        // Simulation of network call or CoreData
        self.data = Service.getSales()
    }
}

struct DashboardView: View {
    @StateObject var viewModel = ChartViewModel()
    
    var body: some View {
        Chart(viewModel.data) { ... }
            .onAppear { viewModel.fetchData() }
    }
}

By keeping the data transformation logic in the ViewModel, your view remains clean and declarative.


Swift Charts vs. Third-Party Libraries

Why should you learn this instead of using Charts (the famous library by Daniel Gindi) or Plot?

  • Binary Weight: Swift Charts is already in the OS. It doesn’t add megabytes to your app.
  • Maintenance: Being official from Apple, you are guaranteed support in future versions of Xcode and Swift.
  • Syntax: It is “SwiftUI-native”. You don’t have to fight with UIViewRepresentable or complex delegates.

Conclusion: The Future is Visual

The Swift Charts framework has democratized data visualization in the Apple ecosystem. It has removed the mathematical barrier to entry that required drawing pixel-by-pixel, allowing any iOS developer to create rich, data-driven interfaces.

Mastering Swift Charts in SwiftUI not only improves the aesthetics of your applications but makes you a more complete developer, capable of communicating complex information simply. Whether you are working on a personal app or at a large company using Xcode to deploy to millions of devices, this tool is indispensable in your Swift programming utility belt.

What is the next step?

I suggest you open Xcode right now. Don’t copy and paste; try to create a simple chart of your “Daily Steps” or “Screen Time”. Experiment with LineMark and BarMark. The best way to learn SwiftUI and Swift Charts is by breaking things and putting them back together.

If you have any questions about this article, please contact me and I will be happy to help you 🙂. You can contact me on my X profile or on my Instagram profile.

Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Article

How to test SwiftUI Views

Next Article

MVC vs MVVM in iOS, Swift and SwiftUI

Related Posts