Logo for tanaschita.com

Making custom SwiftUI controls accessible with accessibilityRepresentation

Learn how to give a custom control the accessibility behavior of a native SwiftUI control.

19 Oct 2026 · 5 min read

Native SwiftUI controls already provide information and interactions that assistive technologies can understand. When we build a control entirely from custom views and gestures, we also become responsible for providing that accessibility behavior.

In this article, we'll build a waveform scrubber and use accessibilityRepresentation to give it the accessibility behavior of a native Slider.

Sponsorship logo
Architecture & Design Patterns for iOS
This book is a practical guide to essential architectural principles and design patterns for iOS development. It covers strategies for building maintainable apps with Swift and SwiftUI, including dependency injection, navigation, common patterns, and modularization.
LEARN MORE

Building a custom waveform scrubber

Suppose an audio player uses a row of bars to visualize its playback progress. Dragging across the waveform changes the current position:

struct WaveformScrubber: View {
@Binding var position: TimeInterval
let duration: TimeInterval
var body: some View {
GeometryReader { geometry in
WaveformBars(progress: duration > 0 ? position / duration : 0)
.contentShape(.rect)
.gesture(
DragGesture(minimumDistance: 0)
.onChanged { value in
guard duration > 0, geometry.size.width > 0 else {
return
}
let progress = min(
max(value.location.x / geometry.size.width, 0),
1
)
position = duration * progress
}
)
}
.frame(height: 44)
}
}

In the full implementation, the individual waveform bars are drawn and sized using GeometryReader. Here, WaveformBars keeps the rendering details out of the example so we can focus on the binding and drag interaction.

The control works with touch, but its appearance and DragGesture don't tell assistive technologies that it represents an adjustable playback position. Adding only an accessibility label would describe the control without providing a way to change its value.

Reusing a Slider's accessibility behavior

The waveform behaves differently from a native Slider visually, but both controls select a value from a bounded range. We can express that relationship by adding accessibilityRepresentation to the complete control:

.accessibilityRepresentation {
Slider(value: $position, in: 0...duration, step: 1) {
Text("Playback position")
}
.accessibilityValue(formattedPosition)
}

The formatted value communicates a playback time instead of a raw number of seconds:

private var formattedPosition: String {
Duration.seconds(position)
.formatted(.time(pattern: .minuteSecond))
}

SwiftUI doesn't display the Slider from the representation. It uses the slider to create the waveform's accessibility label, value, traits and adjustable interaction. Because both controls use the same position binding, changing the value through an assistive technology also updates the visible waveform.

This avoids recreating the semantics of an adjustable control manually and keeps the accessibility behavior aligned with the native control.

Conclusion

accessibilityRepresentation is useful when the visible control needs a genuinely custom implementation but still corresponds to a familiar native control. The waveform is custom-drawn and responds to a drag gesture, while its value and interaction model correspond to a Slider.

Sponsorship logo
Preparing for a technical iOS job interview
Preparing for a technical iOS Job Interview with over 300 questions & answers. Covering Swift & Objective-C, SwiftUI & UIKit, Combine, HTTP Networking, iOS File System, Core Data, Concurrency with async/await, Security, Automated Testing, Dependency Management, AI & Machine Learning and more.
LEARN MORE
Sponsorship logo
Architecture & Design Patterns for iOS
This book is a practical guide to essential architectural principles and design patterns for iOS development. It covers strategies for building maintainable apps with Swift and SwiftUI, including dependency injection, navigation, common patterns, and modularization.
LEARN MORE
Sponsorship logo
Become a sponsor of tanaschita.com
By publishing an article on different iOS topics every week, tanaschita.com is constantly growing in the developer community and may provide a great audience for you as a sponsor.
CLICK TO LEARN MORE

Newsletter

Image of a reading marmot
Subscribe

Like to support my work?

Say hi

Related tags

Articles with related topics

accessibility

swiftui

ios

Supporting Differentiate Without Color in SwiftUI

Learn how to communicate status with symbols and shapes instead of relying on color alone.

12 Oct 2026 · 4 min read

Latest articles and tips

© 2026 tanaschita.com

Privacy policy

Impressum