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
- Open iOS Simulator
- Navigate to Settings > Accessibility > VoiceOver
- Toggle VoiceOver ON
- Use 3-finger swipe to navigate elements
- 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) | |
| accessibilityPerformMagicTap | Triggered when user performs a magic tap (e.g., double-tap with 3D Touch) | |
| accessibilityPerformPress | Triggered when user performs a press gesture (e.g., long-press) | |
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
Scanfeature 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.