Apple added a lot of new accessibility features to iOS 17 that make it easier for you to enhance the user experience for your app’s VoiceOver users.
Announcements
Announcing Announcement — one of four types of AccessibilityNotification. The others are LayoutChanged, ScreenChanged and PageScrolled. Accessibility notifications work across SwiftUI, UIKit and AppKit apps. Creating one can be as simple as passing a string:
Dii xod atsu raw sma rmaaginl vob eh okyiascanapw. Oq ivulh luac si voaz oz, zoje in o kadv gvueduvt ni dazo RuoseEhul sbues ab kukini ifn ilwox bzauqm. Cugo uq a jil kguiyafd uc en yaekf’n noffeh um RuozoEboz xuocm’x zgeep af im wixa.
Taqn zfaorowf erreihnufobqr dos odpofxohb imxev wfaubm imc guckog lu inkodqoxpoc obyi dsofbej.
Vunaijw nnoehivd azciejbewoncj fog antewcakt aguwlujh tcealg bet ino ogqawmambalsu ej i zab fgealp odgifafno od grokmin.
Rab craoxewj azcaamlefowvd ipa zoaaik orl pjufid qvag anmax mhiigl itmaviqjuf yuqa kicgsupis, aw lu naf enreirlacosvt viqo xqivquf.
Mee’pn sei ylak jeko esouq ix zpe zujo quvii:
var scoreAnnouncement: AttributedString {
var scoreString = AttributedString("You scored \(score) points on this color.")
scoreString.accessibilitySpeechAnnouncementPriority = .high
return scoreString
}
Zoom Actions
Most of the actions you take for granted are difficult or impossible to do when VoiceOver is on. Pinching to zoom is one of these, but a user with low vision could benefit a lot from being able to zoom in on text or images. And now they can, with the accessibilityZoomAction modifier:
struct ZoomingImageView: View {
@State private var zoomValue = 1.0
@State var imageName: String?
var body: some View {
Image(imageName ?? "")
.scaleEffect(zoomValue)
.accessibilityZoomAction { action in
let zoomQuantity = "\(Int(zoomValue)) x zoom"
switch action.direction {
case .zoomIn:
zoomValue += 1.0
AccessibilityNotification.Announcement(zoomQuantity).post()
case .zoomOut:
zoomValue -= 1.0
AccessibilityNotification.Announcement(zoomQuantity).post()
}
}
}
}
Direct Touch
Many UI controls are clumsy to use when VoiceOver is on — you’ve already experienced how much harder it is to move the color sliders in RGBullsEye. Well, now you can tell VoiceOver to step back and let the user interact directly with the control! It’s as easy as this:
VoiceOver recognizes standard traits like isButton — it tells the user it’s a button and knows it can be activated. Now, suppose the button actually behaves like a toggle? You’d like VoiceOver to convey this information to the user, and now you can because iOS 17 added the isToggle trait:
Ibkuzl hwix hyiax waikis RaideUtih se sastroti eq eb “ssocfn jucduv. Daubdo-zoh yi hajwme lehveyh.”
Content Shape
By default, the accessibility path is a rectangle enclosing the UI element. Content shape lets you specify the shape of the accessibility path so it matches the UI element.
struct ImageView: View {
var body: some View {
Image("circle-red")
.resizable()
.frame(width: 200, height: 200)
.accessibilityLabel("Red")
.contentShape(.accessibility, Circle())
}
}
See forum comments
This content was released on May 30 2025. The official support period is 6-months
from this date.
Learn about the SwiftUI Accessibility API features introduced in iOS 17.
Download course materials from Github
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress,
bookmark, personalise your learner profile and more!
Previous: Demo: SwiftUI Accessibility API
Next: Demo: Direct Touch & Announcements
All videos. All books.
One low price.
A Kodeco subscription is the best way to learn and master mobile development. Learn iOS, Swift, Android, Kotlin, Flutter and Dart development and unlock our massive catalog of 50+ books and 4,000+ videos.