Skip to content

Audio Graphs (SwiftUI)

A SwiftUI guide for coding agents. Also covers accessibilitychartdescriptor, axchartdescriptor, voiceover chart sound, accessible bar chart ios, sonified data.

Audio Graphs (iOS 15+) let VoiceOver play a chart as sound: high pitches for large values, low pitches for small ones, reached through the rotor menu. The accessibilityChartDescriptor view modifier attaches that audio representation to any view that draws data, even an image.

Describe the Chart Data

Conform a type to AXChartDescriptorRepresentable and implement makeChartDescriptor(), which returns an AXChartDescriptor. Axis descriptors carry the structure: categorical for string labels, numeric for values.

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]
    )
  }
}

Two decisions encode the chart type: a bar chart uses AXCategoricalDataAxisDescriptor on X and isContinuous: false; a line chart uses numeric descriptors on both axes and isContinuous: true.

Attach It to the View

Collapse the drawn chart into one accessibility element, give it a label, then attach the descriptor.

BarChartView(dataPoints: dataPoints)
  .accessibilityElement()
  .accessibilityLabel("Chart representing some data")
  .accessibilityChartDescriptor(self)

VoiceOver then offers the audio graph in the rotor. The view itself can be anything, a custom HStack of bars or a rendered image, because the descriptor, not the pixels, carries the data.

Use this guidance in your coding agent

Install the Better Design MCP once. Your agent then loads this page with one call.

get-swiftui-guide({ topic: "swiftui-audio-graphs" })
claude mcp add --scope user better-design --transport http https://better-design.com/api/mcp --header "Authorization: Bearer <YOUR_API_KEY>"
Browse related design systems