Mobile Development 9 min read

Implementing Audio Charts in SwiftUI for iOS Accessibility

This tutorial shows how to create a SwiftUI bar chart, define a DataPoint model, and enhance its accessibility by conforming to AXChartDescriptorRepresentable and applying the accessibilityChartDescriptor modifier, enabling iOS 15’s Audio Charts feature that conveys chart values through pitch‑varying VoiceOver tones.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Implementing Audio Charts in SwiftUI for iOS Accessibility

Charts are one of the more complex things in terms of accessibility. iOS 15 introduced a new feature called "Audio Charts".

This tutorial demonstrates how to build audio representations for any SwiftUI view using the accessibilityChartDescriptor view modifier, presenting charts like custom bar chart views or images.

DataPoint Struct

Let's start by building a simple bar chart view in SwiftUI that displays a set of data points using vertical bars.

struct DataPoint: Identifiable {
let id = UUID()
let label: String
let value: Double
let color: Color
}

Here we have a DataPoint struct that describes a bar in the bar chart view. It has an id, label, value, and fill color.

BarChartView Struct

Next, we can define a bar chart view that takes an array of DataPoint struct instances and displays them.

struct BarChartView: View {
let dataPoints: [DataPoint]
var body: some View {
HStack(alignment: .bottom) {
ForEach(dataPoints) { point in
VStack {
RoundedRectangle(cornerRadius: 8, style: .continuous)
.fill(point.color)
.frame(height: point.value * 50)
Text(point.label)
}
}
}
}
}

As shown above, we have a BarChartView that takes an array of DataPoint instances and displays them as rounded rectangles of varying heights in a horizontal stack.

ContentView Struct

We can easily build a bar chart view in SwiftUI. Next, let's try using BarChartView with sample data.

struct ContentView: View {
@State private var dataPoints = [
DataPoint(label: "1", value: 3, color: .red),
DataPoint(label: "2", value: 5, color: .blue),
DataPoint(label: "3", value: 2, color: .red),
DataPoint(label: "4", value: 4, color: .blue),
]
var body: some View {
BarChartView(dataPoints: dataPoints)
.accessibilityElement()
.accessibilityLabel("Chart representing some data")
}
}

Here we create a sample array of DataPoint instances and pass it to BarChartView . We also create an accessibility element for the chart and disable accessibility information for its children. To improve the accessibility experience of the chart view, we also added an accessibility label.

Finally, we can start implementing the Audio Charts feature for our bar chart view. Audio Charts are available through the rotor menu. To use the rotor, rotate two fingers on the screen of your iOS device as if you're turning a dial. VoiceOver will speak the first rotor option. Continue rotating your fingers to hear more options. Lift your finger to select Audio Chart. Then swipe up or down on the screen to navigate.

Audio Charts allow users to understand and interpret chart data using audio components. VoiceOver plays sounds with different pitches when moving to bars in the chart view. VoiceOver uses higher pitches for larger values and lower pitches for smaller values. These tones represent the data in the array.

Implementing the Protocol

Now we can discuss the method to implement this feature in BarChartView. First, we must create a type that conforms to the AXChartDescriptorRepresentable protocol. The AXChartDescriptorRepresentable protocol has only one requirement: creating an instance of type AXChartDescriptor . An instance of type AXChartDescriptor represents the data in our chart in a format that VoiceOver can understand and interact with.

extension ContentView: AXChartDescriptorRepresentable {
func makeChartDescriptor() -> AXChartDescriptor {
let xAxis = AXCategoricalDataAxisDescriptor(
title: "Labels",
categoryOrder: dataPoints.map(\.label)
)
let min = dataPoints.map(\.value).min() ?? 0.0
let max = dataPoints.map(\.value).max() ?? 0.0
let yAxis = AXNumericDataAxisDescriptor(
title: "Values",
range: min...max,
gridlinePositions: []
) { value in "\(value) points" }
let series = AXDataSeriesDescriptor(
name: "",
isContinuous: false,
dataPoints: dataPoints.map {
.init(x: $0.label, y: $0.value)
}
)
return AXChartDescriptor(
title: "Chart representing some data",
summary: nil,
xAxis: xAxis,
yAxis: yAxis,
additionalAxes: [],
series: [series]
)
}
}

All we need to do is conform to the AXChartDescriptorRepresentable protocol and add the makeChartDescriptor function that returns an instance of AXChartDescriptor .

First, we define the X and Y axes by using the AXCategoricalDataAxisDescriptor and AXNumericDataAxisDescriptor types. We want to use string labels on the X axis, which is why we use the AXCategoricalDataAxisDescriptor type. For line charts, we would use AXNumericDataAxisDescriptor type on both axes.

Implementing Line Charts

Next, we define the points in the chart using the AXDataSeriesDescriptor type. There is an isContinuous parameter that allows us to define different chart styles. For example, for bar charts, it should be false, while for line charts, it should be true.

struct ContentView: View {
@State private var dataPoints = [
DataPoint(label: "1", value: 3, color: .red),
DataPoint(label: "2", value: 5, color: .blue),
DataPoint(label: "3", value: 2, color: .red),
DataPoint(label: "4", value: 4, color: .blue),
]
var body: some View {
BarChartView(dataPoints: dataPoints)
.accessibilityElement()
.accessibilityLabel("Chart representing some data")
.accessibilityChartDescriptor(self)
}
}

As a final step, we use the accessibilityChartDescriptor view modifier to set the instance conforming to the AXChartDescriptorRepresentable protocol as the instance describing our chart.

Summary

Audio Charts feature is a significant improvement for users with visual impairments. The benefit of the Audio Charts feature is that it can be used for any view you want, including image views. Simply create an instance of type AXChartDescriptor .

Mobile DevelopmentaccessibilityiOS DevelopmentSwiftUIUIKitAudio ChartsAXChartDescriptorVoiceOver
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.