Making UILabel Accessible

Sam Dods
Kin + Carta Created
4 min readOct 9, 2019

When it comes to arguing the benefits of a mobile app vs. a mobile website, it’s pretty easy to sell the advantages of the former, in my opinion!

However, one major advantage mobile web has over an app is that all text on a web page is selectable. That’s not the case for a mobile app.

UITextView supports selection through its isSelectable property, whereas UILabel does not. This can make for an annoying user experience when a user wants to copy some text from your app.

What’s worse is that without text selection, you cannot support the native accessibility feature Speak Selection.

Speak Selection

This is an accessibility feature enabled in iOS Settings app > Accessibility > Spoken Content > Speak Selection (switch on/off).

If Speak Selection is turned on, when text is selected, the usual menu that appears to show contextual actions, such as Copy and Paste, also includes the Speak option.

Long press to bring up the contextual menu where you’ll find the “Speak” option

As an app developer, you get this for free when using a `UITextView` to display text.

However, because UILabel doesn’t support text selection, you need to implement custom logic to present this menu and support text-to-speech.

Copy text

Accessibility doesn’t just refer to improving the experience for users with disabilities. We shouldn’t just think about text selection for speaking as an improvement in accessibility. Allowing text selection for the purpose of copying is an improvement in accessibility too. Giving users the ability to copy product names, ingredients, contact details, prices and other text improves the all-round experience.

Being able to copy text means your users can then paste text into, say, a text message or a language translation tool. It may be harder for some users to remember even short pieces of text, so being able to copy and paste is really important.

Because both require text selection, it makes sense to support Speak and Copy at the same time.

Selecting text in a UILabel

Because a UILabel generally holds short pieces of text, it seems acceptable to select the content in its entirety, rather than allow selection of individual words like UITextView does.

The steps are as follows:

  1. Create a subclass of UILabel which you will use anywhere you want your label text to be selectable.
  2. Add a long press gesture recogniser.
  3. Upon long press, present the UIMenuController shared instance with the menu items you need, in this case, Copy and Speak. (You might choose only to add the Speak option if UIAccessibility.isSpeakSelectionEnabled == true, but there’s no harm in always giving the users this option!)
  4. Implement methods for copying and speaking, which are called when your menu items are tapped.
  5. Optionally, I suggest highlighting your text with a dark overlay to indicate what is selected. UIMenuController posts a notification when it hides, so you can observe that and dismiss your overlay.

Pretty straightforward, right? Let’s see what the code looks like…

SelectableLabel

The below is a snippet showing the important functionality:

Breaking this down, we have:

  1. Initialisation and setup. Adding the overlay view, which will be shown/hidden when focus is given to the label. Adding the long press gesture recogniser. Observing the UIMenuController.didHideMenuNotification notification in order to hide our overlay.
  2. Hide the overlay when the menu hides.
  3. Responding to the long press gesture. Make the label first responder. This is so we can hide the overlay when the label resigns first responder. Create the menu and set its target rect. Setup the menu items with Copy and Speak options, then show the menu.
  4. Responding to user selecting the Copy and Speak options. Copy is simple, just copy the string to the clipboard (UIPasteboard.general). Speak is slightly more involved. Specifying .duckOthers means that any other audio such as music will be reduced in volume to allow the spoken text to be heard.
  5. Create a speech synthesizer. If it’s already speaking, then stop at the next word boundary, using .word option. Set the “utterance” to the label’s text and then speak it out loud.

Speech Synthesizer shared instance

The speech synthesizer is implemented like so:

The purpose of this speech synthesizer extension is to provide a shared instance that has a delegate. The delegate is a shared instance of private class SpeechDelegate, which is responsible for deactivating the audio session once the utterance has finished.

The result

We now have a label that we can use anywhere in the app, in place of a UILabel. When long pressed, a menu is presented like so:

Long press the label to reveal the contextual menu

The complete code for this is on GitHub.

This improves the user experience for everyone, not just those with specific accessibility needs. I really recommend adding Copy and Speak to the labels in your own apps. Perhaps it’s not necessary to add it to every label, but I don’t see any harm.

Any questions, give me a shout on Twitter. 👋

If you want to join me and the TAB team in our quest to make better user experiences for everyone, check out our roles and benefits and please get in touch.

Now hiring in Edinburgh! 🏴󠁧󠁢󠁳󠁣󠁴󠁿🚀

--

--

Sam Dods
Kin + Carta Created

Tech Lead and Mobile Evangelist based in Edinburgh, Scotland