How it works
AccessibilityRotorContentBuilder is the result builder that assembles the contents of a custom accessibility rotor. When you call accessibilityRotor(_:), the trailing closure is annotated with this builder, so the expressions you write inside it are collected into the ordered set of entries that VoiceOver presents when a user selects the rotor. Reach for it whenever you want to give assistive-technology users a fast, navigable index into a screen's important content rather than forcing them to swipe through every element in sequence.
Open a rotor closure with accessibilityRotor(_:)
Attaching
accessibilityRotor("Folders")to a view declares a named rotor and hands you a content closure. That closure is whereAccessibilityRotorContentBuilderdoes its work: it transforms the views you list into the rotor's navigation entries. Here the rotor is applied to theScrollView, scoping the rotor to that scrollable region.Produce entries inside the builder
Inside the builder closure you describe entries rather than visible UI. Each
AccessibilityRotorEntry(name, id: name, in: "folders")becomes one stop in the rotor, and the builder gathers them into the final ordered list. The first argument supplies the label VoiceOver speaks, whileidand the namespace"folders"tell SwiftUI which on-screen element the entry points to.Generate entries dynamically with ForEach
Because
AccessibilityRotorContentBuilderunderstandsForEach, you can build entries from a collection instead of writing them by hand. IteratingForEach(messages, id: \.self)emits one entry per element ofmessages, so the rotor's contents stay in sync with the data driving the view.Anchor each entry to a real view
An entry is only useful if it can move focus to something on screen. The matching
.accessibilityRotorEntry(id: name, in: "folders")modifier on eachTextregisters that view in the"folders"namespace, and the entry's sharedidand namespace let the rotor jump VoiceOver focus directly to it.
ForEach(messages, id: \.self) down to a subset, such as iterating messages.filter { $0.hasPrefix("S") }, and observe that the rotor now lists only Sent, even though every folder still appears in the scroll view.Example & preview
Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.
struct AccessibilityRotorContentBuilderDemo: View {
let messages = ["Inbox", "Drafts", "Sent", "Archive"]
var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 12) {
ForEach(messages, id: \.self) { name in
Text(name)
.font(.headline)
.accessibilityRotorEntry(id: name, in: "folders")
}
}
.padding()
}
.accessibilityRotor("Folders") {
ForEach(messages, id: \.self) { name in
AccessibilityRotorEntry(name, id: name, in: "folders")
}
}
}
}