Accessibility in iOS Apps, Automation Behaviours and VoiceOver Mode with a Demo Project

This article covers all subjects mentioned in the title in a basic way.

Mücahit Eren Özkur
DigiGeek
5 min readJul 20, 2023

--

Accessibility in iOS refers to the practice of making your app inclusive and usable for all users, including those with disabilities. Apple places a strong emphasis on accessibility, providing a range of tools and features to help developers create apps that can be easily navigated and interacted with by individuals who may have visual, auditory, or motor impairments.

VoiceOver is an accessibility feature provided by Apple on iOS devices, including iPhones, iPads, and iPod Touch. It is designed to assist users with visual impairments by providing spoken feedback and descriptions of the content displayed on the screen. With VoiceOver enabled, users can navigate their device, interact with apps, and access various features using touch gestures and the device’s accessibility gestures.

You can give quick access for test purposes by clicking your power button 3 times when below setting is arranged.

Opening VoiceOver shortcut

Also, you can monitorize accessibility features and more from “Accessibility Inspector” tool by clicking Xcode → Open Developer Tool → Accessibility Inspector.

Accessibility Properties

There are some attributes that helps VoiceOver work and give assistive information. Let’s mention the ones that developers mostly use when they work on it.

/***
A Boolean value that indicates whether the element is an accessibility element
that an assistive app can access.
***/
var isAccessibilityElement: Bool

// An array of specified accessibility elements in the container.
var accessibilityElements: [Any]?

// A string that identifies the element for automation and distinction purposes.
var accessibilityIdentifier: String?

/***
A succinct label in a localized string
that identifies the accessibility element.
***/
var accessibilityLabel: String?

// A localized string that contains the value of the accessibility element.
var accessibilityValue: String?

/***
A localized string that contains a brief description of the result
of performing an action on the accessibility element.
***/
var accessibilityHint: String?

// Constants that describe how an accessibility element behaves.
struct UIAccessibilityTraits

We generally use the first four of the above attributes. They are sufficient in most cases.

Automation

If your company uses Automation for your project, one of the attributes is vital for locating the elements in platforms like Appium. It is called accessibilityIdentifier.

Once you start to give ids to related UI elements, they will be accessible and visible in automation tools. It is very basic to accomplish this task. There are 2 ways of doing it.

First one is via code;

@IBOutlet private weak var numberLabel: UILabel!

numberLabel.accessibilityIdentifier = "Age"

Second way is giving the id from identity inspector in XIB file;

Giving accessibilityIdentifier from XIB

After that, you can see and verify the given ids in runtime debug mode or more easily and preferably, we can open accessibility inspector, hang around the UI elements and see the values in panel;

Monitoring accessibility id from accessibility inspector tool

Demo Project

Let’s create a view controller to see these functions in action. I want to have a page that shows us in the top a title. Below that, I want to see 4 actor/actresses pictures, their names and which season they were born in.

Basically, the code block should be something like this:

//
// ActorsVC.swift
// Demo
//
// Created by MUCAHIT EREN OZKUR on 19.07.2023.
// Copyright © 2023 Turkcell. All rights reserved.
//

import UIKit

final class ActorsVC: UIViewController {

// MARK: - IBOutlets
@IBOutlet private weak var titleLabel: UILabel!
@IBOutlet private weak var nameLabel: UILabel!
@IBOutlet private weak var profileImageView: UIImageView!
@IBOutlet private weak var seasonLabel: UILabel!

// MARK: - Life Cycle Methods
override func viewDidLoad() {
super.viewDidLoad()
prepareAccessibilityElements()
accessibilityElements = [titleLabel as Any,
profileImageView as Any,
nameLabel as Any,
seasonLabel as Any]
}

// MARK: - Functions
private func prepareAccessibilityElements() {
profileImageView.isAccessibilityElement = true
profileImageView.accessibilityLabel = "This is an actor profile image."
profileImageView.accessibilityIdentifier = "ImageArea"

titleLabel.accessibilityIdentifier = "TitleArea"
nameLabel.accessibilityIdentifier = "NameArea"
seasonLabel.accessibilityIdentifier = "SeasonArea"
}
}

After I declared my IBOutlets, I had to create a function to call in viewDidLoad. That’s why I created prepareAccessibilityElements() function.

In this function, I gave IBOutlets’ accessibilityIdentifiers for mostly automation purposes.

Also, I defined profileImageView as an accessibility element. You need to specify it explicitly for Images. Labels are just fine.

Moreover, I used accessibilityLabel for my image view to inform my user as what I want him/her to hear rather than hearing the accessibility identifier.

Then, I call the function and for the last part, I added these IBOutlets into accessibilityElements array to tell “these are my accessibility UI elements, go and find them when someone is using VoiceOver mode”.

Now, I run the app in my phone and enabled the VoiceOver mode to see if there is a reaction. Here is the result:

VoiceOver transitions

I achieved to go thorough among UI elements in my phone. We can navigate from up to down and walk around every UI element in the page. This is based on which order you place the IBOutlets into the accessibilityElements array.

Order matters.

And that’s it! If you have any questions, feel free to ask me and let’s talk about it.

See you soon.

--

--