Skip to main content

Working with Accessibility

1. Using Accessibility Labels

Property Description Usage
accessibilityLabel Defines a string that identifies the element for VoiceOver. button.accessibilityLabel = "Submit Form"
accessibilityHint Provides a brief description of what happens when the element is activated. button.accessibilityHint = "Taps to submit the form"
accessibilityValue Represents the current value of an adjustable element. slider.accessibilityValue = "50%"

Example: Setting Accessibility Label

let button = UIButton()
button.accessibilityLabel = "Save Changes"
button.accessibilityHint = "Taps to save the current changes"
Note: Always provide meaningful labels that help users understand the purpose of UI elements.

2. Using Accessibility Hints

Property Value Description
accessibilityHint String? Provides a brief description of what happens when the user performs an action on the element.

Example: Setting an Accessibility Hint

button.accessibilityHint = "Taps the button to submit the form"
Note: The hint is only read by screen readers when the user performs an action on the element.

3. Using Accessibility Traits

Property Description Values
accessibilityTraits Defines the role or function of a UI element for VoiceOver accessibilityTraits is a set of UIAccessibilityTraits that describe the element's purpose.

Example: Setting Accessibility Traits

let button = UIButton()
button.accessibilityTraits = [.button, .allowsDirectInteraction]
Note: Traits should reflect the actual behavior of the element, not just its appearance.
Trait Description Usage
button Indicates the element is a button Use for interactive elements that perform an action
link Indicates the element is a link Use for elements that navigate to another page or resource
header Indicates the element is a header Use for section headers or titles
image Indicates the element is an image Use for static or dynamic images
allowsDirectInteraction Indicates the element can receive direct interaction Use for elements that support touch or voice input

4. Setting Accessibility Values

Property Value Description
accessibilityLabel String? Human-readable label for the element, used by screen readers
accessibilityHint String? Short description of what happens when the element is activated
accessibilityValue String? Current value of the element, e.g., slider position or text field content
accessibilityTraits UIAccessibilityTraits Defines the semantic role of an element (e.g., button, link, header)
accessibilityFrame CGRect? Custom frame for accessibility if the view's frame is not accurate

Example: Setting Accessibility Values on a Button

let button = UIButton()
button.accessibilityLabel = "Submit Form"
button.accessibilityHint = "Taps to submit the form and navigate to next screen"
button.accessibilityValue = "Not submitted"
button.accessibilityTraits = .button

Example: Setting Accessibility Value on a Slider

let slider = UISlider()
slider.accessibilityLabel = "Volume Control"
slider.accessibilityValue = "\(slider.value)%"
slider.accessibilityTraits = .adjustable
Note: For dynamic content, update accessibilityValue whenever the value changes to ensure screen readers provide accurate information.

5. Grouping Accessibility Elements

Grouping accessibility elements helps screen readers navigate content more efficiently by organizing related elements into logical containers.

Property Description Usage
accessibilityGroup Boolean value indicating whether the element should be grouped with others for accessibility purposes. view.accessibilityGroup = true
accessibilityElements Array of accessibility elements that are grouped together. view.accessibilityElements = [button1, button2]

Example: Grouping Buttons

let group = UIView()
group.accessibilityGroup = true

let button1 = UIButton()
button1.accessibilityLabel = "Save"
button1.accessibilityHint = "Saves the document"

let button2 = UIButton()
button2.accessibilityLabel = "Cancel"
button2.accessibilityHint = "Cancels the current operation"

group.accessibilityElements = [button1, button2]
Note: When accessibilityGroup is set to true, the system treats all child elements as a single unit for screen reader navigation.

6. Using VoiceOver Testing

Example: Enabling VoiceOver in Simulator

// In iOS Simulator, go to Settings > General > Accessibility > VoiceOver
// Toggle VoiceOver on to test accessibility features
Accessibility Feature Description Testing Method
VoiceOver Screen reader for visually impaired users Enable in Settings > Accessibility > VoiceOver
Dynamic Type Adjusts text size based on user preferences Test with different Dynamic Type sizes in Settings > Display & Brightness > Text Size
Color Contrast Ensures sufficient contrast for readability Use Settings > Display & Brightness > Color Filters to test

Workflow: Testing VoiceOver Navigation

  1. Open iOS Simulator
  2. Navigate to Settings > Accessibility > VoiceOver
  3. Toggle VoiceOver ON
  4. Use 3-finger swipe to navigate elements
  5. Verify that all UI elements are announced correctly

Comparison: VoiceOver vs. Accessibility Inspector

  • VoiceOver: Simulates real user interaction with screen reader
  • Accessibility Inspector: Analyzes accessibility properties without user interaction
Note: Always test with actual VoiceOver enabled, as simulator behavior may differ from real device behavior.

7. Supporting Dynamic Type

Dynamic Type allows users to adjust text sizes in iOS, ensuring content remains readable. Supporting Dynamic Type is crucial for accessibility compliance.

Property Value Description
UIFont.TextStyle .largeTitle, .title1, .body, etc. Predefined text styles that scale with Dynamic Type
UIFontMetrics UIFontMetrics.default Used to scale fonts based on Dynamic Type settings

Example: Using Dynamic Type in UI

let label = UILabel()
label.font = UIFont.preferredFont(forTextStyle: .title1)
label.adjustsFontForContentSizeCategory = true

Example: Custom Font Scaling

let customFont = UIFont.systemFont(ofSize: 16)
let scaledFont = UIFontMetrics.default.scaledFont(for: customFont)
label.font = scaledFont
Note: Ensure that your layout adapts to different text sizes. Avoid fixed frame constraints and use Auto Layout for better responsiveness.

8. Implementing Custom Actions

Action Description Implementation
accessibilityPerformEscape Triggered when user performs escape gesture (e.g., double-tap with 3D Touch)
override func accessibilityPerformEscape() -> Bool {
    // Handle escape action
    return true
}
accessibilityPerformMagicTap Triggered when user performs a magic tap (e.g., double-tap with 3D Touch)
override func accessibilityPerformMagicTap() -> Bool {
    // Handle magic tap action
    return true
}
accessibilityPerformPress Triggered when user performs a press gesture (e.g., long-press)
override func accessibilityPerformPress() -> Bool {
    // Handle press action
    return true
}

Example: Custom Action Implementation

class CustomView: UIView {
    override func accessibilityPerformEscape() -> Bool {
        // Example: Close a modal view
        if let modalViewController = self.superview?.window?.rootViewController?.presentedViewController {
            modalViewController.dismiss(animated: true)
        }
        return true
    }

    override func accessibilityPerformMagicTap() -> Bool {
        // Example: Toggle a feature
        self.isAccessibilityElement = !self.isAccessibilityElement
        return true
    }
}
Note: Custom actions are only available on iOS 13 and later.

9. Using Accessibility Notifications

Accessibility notifications allow apps to communicate important information to users who rely on assistive technologies like VoiceOver. These notifications can be used to announce events, status changes, or other relevant information.

Notification Description Usage
UIAccessibilityScreenChangedNotification Announced when the screen content changes significantly. NotificationCenter.default.post(name: UIAccessibilityScreenChangedNotification, object: nil)
UIAccessibilityLayoutChangedNotification Announced when the layout of the screen changes (e.g., a new view appears). NotificationCenter.default.post(name: UIAccessibilityLayoutChangedNotification, object: nil)
UIAccessibilityAnnouncementDidFinishNotification Posted when an announcement finishes. NotificationCenter.default.post(name: UIAccessibilityAnnouncementDidFinishNotification, object: nil)

Example: Posting an Accessibility Notification

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Post a screen change notification
        NotificationCenter.default.post(name: UIAccessibilityScreenChangedNotification, object: nil)
    }
    
    @IBAction func announceButtonTapped(_ sender: UIButton) {
        // Announce a message to VoiceOver users
        UIAccessibility.post(notification: .announcement, argument: "Button was tapped successfully")
    }
}
Note: Ensure that accessibility notifications are only sent when necessary to avoid overwhelming users.
Warning: Avoid posting too many notifications in quick succession, as this can interfere with the user's ability to process information.

10. Testing with Accessibility Inspector

Example: Using Accessibility Inspector

import XCTest

class AccessibilityTests: XCTestCase {
    func testAccessibility() {
        let app = XCUIApplication()
        app.launch()
        
        // Check if elements are accessible
        XCTAssert(app.staticTexts["Welcome Message"].exists)
        
        // Verify accessibility labels
        XCTAssertEqual(app.staticTexts["Welcome Message"].label, "Welcome to our app")
    }
}
Element Property Description
accessibilityLabel String Descriptive label for screen readers
accessibilityValue String Current value of the element
accessibilityHint String Short description of action
accessibilityTraits UIAccessibilityTraits Defines the element's role (e.g., button, image)
Note: The Accessibility Inspector is part of Xcode's Developer Tools and can be found in Xcode > Open Developer Tool > Accessibility Inspector.
Warning: Ensure all UI elements have appropriate accessibility labels to comply with WCAG guidelines.

Accessibility Inspector Workflow

  • Open Xcode and navigate to Xcode > Open Developer Tool > Accessibility Inspector
  • Launch your app in debug mode
  • Select your app from the list of running apps
  • Inspect elements to verify accessibility properties
  • Use the Scan feature to identify issues

11. Supporting Reduce Motion

Property Value Description
UIAccessibility.reduceMotionEnabled Bool Indicates if the user has enabled reduce motion setting.

Example: Check if Reduce Motion is Enabled

import UIKit

if UIAccessibility.reduceMotionEnabled {
    // Adjust animations or transitions to be less intense
    print("Reduce motion is enabled")
} else {
    // Use standard animations
    print("Reduce motion is disabled")
}
Note: When reduceMotionEnabled is true, apps should minimize or disable animations that can cause discomfort or disorientation.

Best Practices for Reduce Motion

  • Use UIAccessibility.reduceMotionEnabled to detect user preference.
  • Provide alternative interactions or reduced animation effects when enabled.
  • Test animations to ensure they don't cause motion sickness or discomfort.

Was this article helpful?