Skip to content

accessibilityRepresentation (SwiftUI)

A SwiftUI guide for coding agents. Also covers accessibilityrepresentation, voiceover custom control, borrow accessibility from toggle, canvas accessibility, custom control a11y ios.

The accessibilityRepresentation view modifier (SwiftUI Release 3, iOS 15+) swaps a view's accessibility element for that of another view. Use it when a custom control behaves like a standard one: borrow the standard control's VoiceOver behaviour instead of rebuilding it.

The Manual Way It Replaces

A custom checkmark image with a long-press gesture reads to VoiceOver as a plain image. Fixing that by hand takes more accessibility modifiers than control logic.

Image(systemName: isSelected ? "checkmark.rectangle" : "rectangle")
  .onLongPressGesture { isSelected.toggle() }
  .accessibilityRemoveTraits(.isImage)
  .accessibilityAddTraits(.isButton)
  .accessibilityAddTraits(isSelected ? .isSelected : [])
  .accessibilityLabel(Text("Checkmark"))
  .accessibilityHint("You can toggle the checkmark")
  .accessibilityAction { isSelected.toggle() }

Borrow a Standard Control

Provide the equivalent standard view in the closure. SwiftUI never renders it; it only copies its accessibility information onto your view, including label, traits, value, and actions.

struct LongPressCheckmark: View {
  @Binding var isSelected: Bool

  var body: some View {
    Image(systemName: isSelected ? "checkmark.rectangle" : "rectangle")
      .onLongPressGesture { isSelected.toggle() }
      .accessibilityRepresentation {
        Toggle(isOn: $isSelected) {
          Text("Checkmark")
        }
      }
  }
}

Pass real bindings into the representation, so VoiceOver actions actually change the state.

Whole Hierarchies, Not Just Controls

The closure can hold a full view tree. A Canvas has no accessibility at all, so represent a custom chart as a stack of labelled elements.

struct BarChartView: View {
  let bars: [Bar]

  var body: some View {
    Canvas {
      // custom drawing here
    }
    .accessibilityRepresentation {
      HStack {
        ForEach(bars) { bar in
          Rectangle()
            .accessibilityLabel(bar.label)
            .accessibilityValue("\(bar.value)")
        }
      }
    }
  }
}

VoiceOver then walks the bars one by one, reading each label and value, while the screen shows the drawn chart.

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-the-power-of-accessibility-representation-view-modifier" })
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