iOS App Accessibility Checklist: How to Support VoiceOver and Assistive Technologies
Building an iOS app that works seamlessly with VoiceOver and other assistive technologies is no longer optional. Apple actively reviews accessibility during the App Store submission process, and users expect inclusive design as a baseline. Beyond compliance, accessible apps reach a wider audience and deliver a better experience for everyone.
This guide is a practical, developer-focused iOS app accessibility checklist for VoiceOver and related assistive technologies. Rather than covering theory, every section gives you concrete implementation steps you can apply today in your SwiftUI or UIKit codebase.
Whether you are a solo founder preparing for launch or a development team auditing an existing app, use this checklist to ensure nothing slips through before you hit “Submit for Review.”
Why Accessibility Matters for Your iOS App in 2026
Over 1.3 billion people worldwide live with some form of disability. In the iOS ecosystem specifically:
- VoiceOver is used by millions of blind and low-vision users daily.
- Dynamic Type adoption has grown steadily since Apple made it a system-wide default option.
- Switch Control, Voice Control, and AssistiveTouch serve users with motor impairments.
- Apple’s accessibility evaluation criteria now influence App Store approval and featured placements.
Making your app accessible is good design, good business, and increasingly a legal expectation in many jurisdictions.
The Complete iOS App Accessibility Checklist for VoiceOver
Below is the full checklist organized by category. Each item includes the what, the why, and a short code example or implementation note so you can act on it immediately.
1. VoiceOver Compatibility
VoiceOver should be able to speak all visible text in your app, and every interactive element must be operable by VoiceOver users. This is the single most important area of your iOS app accessibility checklist.
1.1 Label Every Interactive Element
Every button, link, toggle, slider, and text field needs an accessibility label that clearly describes its purpose.
// SwiftUI
Button(action: { addToCart() }) {
Image(systemName: "cart.badge.plus")
}
.accessibilityLabel("Add to cart")
// UIKit
addButton.accessibilityLabel = "Add to cart"
Checklist items:
- All buttons have descriptive accessibility labels (not just “button” or the icon name).
- Image-only buttons have text labels that describe the action, not the image.
- Decorative images are hidden from VoiceOver using
.accessibilityHidden(true)orisAccessibilityElement = false. - Labels do not include the element type (avoid “Button to add to cart” because VoiceOver already announces the role).
1.2 Set Correct Accessibility Traits
Traits tell VoiceOver how an element behaves. A missing or wrong trait confuses users.
| Element | Expected Trait | SwiftUI Modifier |
|---|---|---|
| Button | .isButton | .accessibilityAddTraits(.isButton) |
| Link | .isLink | .accessibilityAddTraits(.isLink) |
| Header | .isHeader | .accessibilityAddTraits(.isHeader) |
| Selected tab | .isSelected | .accessibilityAddTraits(.isSelected) |
| Static image | .isImage | .accessibilityAddTraits(.isImage) |
| Adjustable (slider, stepper) | .allowsDirectInteraction | Use .accessibilityAdjustableAction |
1.3 Convey State Changes
- When a button is disabled, it must convey its disabled state. Use
.accessibilityRemoveTraits(.isButton)or ensureisEnabled = falsepropagates to assistive tech. - Toggle states (on/off) should be announced. SwiftUI Toggle does this automatically; custom toggles need
.accessibilityValue("on")or.accessibilityValue("off"). - Loading states should post accessibility notifications:
UIAccessibility.post(notification: .announcement, argument: "Loading content").
1.4 Group Related Elements
When a card or row contains multiple text labels (title, subtitle, metadata), group them so VoiceOver reads one coherent description instead of forcing users to swipe through each piece individually.
// SwiftUI
HStack {
Text(product.name)
Text(product.price)
}
.accessibilityElement(children: .combine)
1.5 Logical Reading Order
- VoiceOver reads elements in the order they appear in the view hierarchy. Make sure your layout order matches the logical reading order.
- Use
.accessibilitySortPriority()in SwiftUI to override order when the visual layout differs from the logical sequence. - Test by swiping right through every screen with VoiceOver enabled. If the order feels wrong to you, it feels wrong to your users.
1.6 Handle Custom Controls
If you build a custom component (a star rating, a color picker, a graph), VoiceOver cannot interpret it automatically. You must:
- Set
isAccessibilityElement = true. - Provide a meaningful
accessibilityLabel. - Provide an
accessibilityValuethat reflects the current state (“3 out of 5 stars”). - Add
accessibilityAdjustableActionif the user should be able to change the value. - Add
accessibilityHintif the interaction model is non-obvious.
2. Dynamic Type Support
Dynamic Type allows users to increase or decrease text size system-wide. Apps that ignore it become unusable for low-vision users.
2.1 Use System Text Styles
// SwiftUI
Text("Welcome back")
.font(.title2)
// UIKit
label.font = UIFont.preferredFont(forTextStyle: .title2)
label.adjustsFontForContentSizeCategory = true
2.2 Dynamic Type Checklist
- Every text element uses a system text style or a custom font scaled with
UIFontMetrics. - No text is clipped or truncated at the largest accessibility text sizes (test with AX5 size in the Accessibility Inspector).
- Layouts reflow gracefully. Horizontal layouts should stack vertically when text grows large. Use
@Environment(\.sizeCategory)in SwiftUI to detect this. - Minimum touch targets remain at least 44×44 points even at small text sizes.
- Table cells and collection view cells use self-sizing (no fixed heights).
3. Color and Contrast
| Requirement | Minimum Ratio | Notes |
|---|---|---|
| Normal text (under 18pt) | 4.5:1 | WCAG AA standard |
| Large text (18pt+ or 14pt bold+) | 3:1 | WCAG AA standard |
| UI components and graphics | 3:1 | Icons, borders, focus indicators |
- Never rely on color alone to convey information. Use icons, patterns, or text labels alongside color cues.
- Support Increase Contrast mode by checking
UIAccessibility.isDarkerSystemColorsEnabledand adjusting your palette. - Support Reduce Transparency by using solid backgrounds when
UIAccessibility.isReduceTransparencyEnabledis true. - Test your color scheme with the Xcode Accessibility Inspector’s color contrast calculator.
4. Motion and Animations
- Respect Reduce Motion preferences. Check
UIAccessibility.isReduceMotionEnabledor use@Environment(\.accessibilityReduceMotion)in SwiftUI. - Replace parallax effects, bouncing transitions, and auto-playing animations with simpler alternatives (crossfades or instant transitions).
- Never use flashing content faster than 3 times per second.
5. Keyboard and Hardware Input
- Every screen must be fully navigable using an external keyboard (many VoiceOver users pair a Bluetooth keyboard).
- Respect standard keyboard shortcuts: Tab to move focus, Space/Enter to activate, Escape to dismiss.
- Ensure custom keyboard shortcuts do not conflict with VoiceOver keyboard commands.
- Support Full Keyboard Access introduced in recent iOS versions.
6. Switch Control and Voice Control
- All interactive elements must be reachable via Switch Control scanning.
- Labels must match visible text so Voice Control users can say “Tap [visible label]” and it works. If your button shows “Submit” but the accessibility label says “Send form,” Voice Control fails.
- Test point scanning and item scanning modes with your app.
7. Forms and Text Input
- Every text field has an accessibility label that describes its purpose (“Email address,” “Password”).
- Error messages are announced to VoiceOver immediately when validation fails. Use
UIAccessibility.post(notification: .announcement, argument: errorMessage). - Form fields have the correct
textContentTypeset so autofill works seamlessly. - Keyboard type matches the expected input (
.emailAddress,.phonePad, etc.). - Required fields are indicated both visually and through the accessibility label (“Email address, required”).
8. Navigation and Focus Management
- When a modal or alert appears, VoiceOver focus moves to it automatically. Use
UIAccessibility.post(notification: .screenChanged, argument: modalView). - When a modal is dismissed, focus returns to the element that triggered it.
- Tab bars and navigation bars are properly labeled.
- Use
.accessibilityAddTraits(.isHeader)for section headers so VoiceOver users can navigate by heading using the rotor. - Back buttons have meaningful labels (“Back to Products” instead of just “Back”).
9. Media and Rich Content
- All images that convey meaning have descriptive
accessibilityLabelvalues. - Decorative images are hidden from VoiceOver.
- Videos include captions or subtitles.
- Audio-only content provides a text transcript.
- Media playback controls are fully accessible and labeled.
- Charts and graphs provide a text summary or data table alternative.
10. Notifications and Alerts
- Important status updates (success messages, errors, real-time data changes) are posted as VoiceOver announcements.
- Alerts and action sheets are built with native UIKit/SwiftUI components whenever possible. Custom dialogs require careful manual accessibility configuration.
- Toast-style notifications that auto-dismiss are announced to VoiceOver before they disappear.
How to Test Your iOS App for Accessibility
Writing accessible code is only half the job. You need to test rigorously. Here is a step-by-step testing workflow.
Step 1: Use the Accessibility Inspector in Xcode
Open Xcode and launch the Accessibility Inspector from the Xcode menu (Xcode > Open Developer Tool > Accessibility Inspector). This tool lets you:
- Inspect any element’s accessibility label, value, traits, and hints.
- Simulate VoiceOver output without leaving the Simulator.
- Run an automated audit that catches common issues like missing labels and low contrast.
Step 2: Test with VoiceOver on a Real Device
The Simulator does not fully replicate VoiceOver behavior. On a physical iPhone or iPad:
- Go to Settings > Accessibility > VoiceOver and enable it.
- Navigate your entire app by swiping right (one-finger flick) through every element.
- Activate elements with a double tap.
- Use the rotor (two-finger rotation gesture) to navigate by headings, links, and form fields.
- Verify that every screen is usable without looking at the display.
Pro tip: Set up the Accessibility Shortcut (triple-click Side button) so you can toggle VoiceOver quickly during testing.
Step 3: Test Dynamic Type at All Sizes
- Go to Settings > Accessibility > Display & Text Size > Larger Text.
- Move the slider to the maximum size (AX5).
- Check every screen for clipped text, overlapping elements, and broken layouts.
- Also test at the smallest text size to ensure nothing breaks in the other direction.
Step 4: Test Other Assistive Features
- Enable Reduce Motion and confirm animations are replaced or removed.
- Enable Increase Contrast and check that your UI remains readable.
- Enable Switch Control and navigate through your app using scanning.
- Enable Voice Control and try activating every button by speaking its visible label.
- Connect a Bluetooth keyboard and tab through your interface.
Step 5: Run Automated Accessibility Tests
Add accessibility assertions to your UI test suite:
func testAccessibility() throws {
let app = XCUIApplication()
app.launch()
try app.performAccessibilityAudit()
}
This built-in Xcode method catches missing labels, insufficient contrast, and elements that are too small to tap. Integrate it into your CI/CD pipeline so regressions are caught early.
Quick-Reference Accessibility Checklist Table
Print this or pin it in your project management tool. Check off each item before submission.
| # | Category | Item | Done? |
|---|---|---|---|
| 1 | VoiceOver | All interactive elements have descriptive accessibility labels | |
| 2 | VoiceOver | Correct traits assigned to every element | |
| 3 | VoiceOver | Disabled states are conveyed | |
| 4 | VoiceOver | Related elements are grouped logically | |
| 5 | VoiceOver | Reading order matches logical order | |
| 6 | VoiceOver | Custom controls have label, value, and adjustable actions | |
| 7 | VoiceOver | Focus management on modals and navigation | |
| 8 | Dynamic Type | All text uses system styles or scaled custom fonts | |
| 9 | Dynamic Type | No clipping or truncation at AX5 size | |
| 10 | Dynamic Type | Layouts reflow at large text sizes | |
| 11 | Color | Contrast ratios meet WCAG AA minimums | |
| 12 | Color | Color is not the only way information is conveyed | |
| 13 | Motion | Reduce Motion preference is respected | |
| 14 | Input | Full keyboard navigation works | |
| 15 | Input | Switch Control and Voice Control tested | |
| 16 | Forms | All fields labeled and errors announced | |
| 17 | Media | Images described, videos captioned | |
| 18 | Testing | Accessibility Inspector audit passes | |
| 19 | Testing | Manual VoiceOver testing on a real device completed | |
| 20 | Testing | Automated accessibility tests in CI/CD |
Common VoiceOver Mistakes to Avoid
Even experienced iOS developers make these errors. Watch out for them:
- Redundant role in labels. Writing “Search button” as the label when VoiceOver already says “button” after the label. Just use “Search.”
- Forgetting to hide decorative elements. Dividers, background shapes, and decorative icons that are not hidden from VoiceOver create noise and slow down navigation.
- Not testing with VoiceOver actually enabled. The Accessibility Inspector is helpful but it does not replace a real VoiceOver walkthrough. The gestures, timing, and experience are different.
- Broken focus after navigation. Pushing a new view controller and not moving focus to the new content forces VoiceOver users to hunt for where they are.
- Using custom gestures without alternatives. If your app requires a three-finger swipe for a feature, provide a button alternative that VoiceOver users can activate.
- Ignoring the VoiceOver rotor. Section headers should have the
.isHeadertrait so users can jump between sections quickly using the rotor.
Accessibility and App Store Review
Apple’s App Store Review Guidelines explicitly mention accessibility. While they will not reject most apps solely for accessibility issues, apps that are completely unusable with VoiceOver can face rejection, especially if they target education, health, or government sectors.
In 2026 and beyond, accessibility is also a growing factor in App Store editorial features. Apple regularly highlights apps with excellent accessibility in curated collections. Getting featured can drive significant organic downloads.
Beyond the App Store, legal frameworks like the ADA (United States), EAA (European Accessibility Act, effective June 2025), and EN 301 549 require digital products to meet accessibility standards. Making your app accessible now protects you from future legal risks.
Tools and Resources for iOS Accessibility Development
- Xcode Accessibility Inspector – Built-in tool for auditing and inspecting accessibility properties.
- Apple VoiceOver evaluation criteria – Official Apple documentation outlining what VoiceOver expects from your app (developer.apple.com).
- WCAG 2.2 Guidelines – The international standard for digital accessibility.
- Deque University iOS Accessibility Checklist – Comprehensive reference for WCAG compliance on iOS.
- performAccessibilityAudit() – Xcode XCTest method for automated accessibility testing in your CI pipeline.
How VRS App Can Help
At VRS App, we help companies build iOS applications that are accessible from day one. Our development process includes accessibility audits at every sprint, VoiceOver testing on real devices, and compliance verification against WCAG 2.2 AA standards. If you are preparing an app for launch or need to retrofit accessibility into an existing product, get in touch with our team to discuss your project.
Frequently Asked Questions
What is the most important item on an iOS app accessibility checklist for VoiceOver?
Descriptive accessibility labels on every interactive element. Without labels, VoiceOver users cannot identify buttons, links, or form fields. This single item affects usability more than any other accessibility feature.
How do I enable VoiceOver for testing on iPhone?
Go to Settings > Accessibility > VoiceOver and toggle it on. For faster access, set up the Accessibility Shortcut by going to Settings > Accessibility > Accessibility Shortcut and selecting VoiceOver. Then triple-click the Side button to toggle it on and off.
Can my iOS app be rejected from the App Store for poor accessibility?
While Apple does not reject every app with accessibility issues, apps that are completely unusable with assistive technologies can face rejection. Apps in regulated categories (education, health, finance) face stricter scrutiny. Meeting basic VoiceOver compatibility is strongly recommended before submission.
What is the difference between accessibilityLabel and accessibilityHint?
The label describes what an element is (“Delete message”). The hint describes what will happen when you interact with it (“Moves the message to trash”). VoiceOver reads the label immediately and the hint after a short pause. Always set the label; use hints sparingly for non-obvious interactions.
Do SwiftUI apps handle accessibility better than UIKit apps?
SwiftUI provides more accessibility support out of the box. Standard controls like Button, Toggle, and Slider automatically set the correct traits. However, custom views still require manual accessibility configuration in both frameworks. The key difference is that SwiftUI modifiers like .accessibilityLabel() and .accessibilityElement(children:) are more concise and easier to maintain.
How often should I test my iOS app for accessibility?
Test accessibility in every sprint or release cycle. Include automated accessibility audits in your CI/CD pipeline and schedule manual VoiceOver testing on real devices at least once per major feature release. Accessibility regressions happen easily when UI changes are made, so continuous testing is essential.