iOS Accessibility Notifications


A screenshot with a thumb next to a thought bubble: Success!
Simple Voice Over Announcement Notification: Success!

What iOS Accessibility Notifications Do

Have you ever noticed when you're navigating around an iOS App how VoiceOver will spontaneously announce something. Or focus will move randomly when you don't expect it to.

Whether it is called by the Operating System or the Engineer of the Application, these behaviors are caused by UIAccessibility Notifications. There are three of these notifications that iOS Application Engineers will utilize frequently:

  1. Announcement
  2. Layout Changed
  3. Screen Changed

Each of these is called in the same way:

post(
    notification: UIAccessibility.Notification,
    argument: Any?
)

Declaration: UIAccessibility.post

This function takes two arguments. The first argument is one of our Notification Type: announcement, layoutChanged, screenChanged.

The second argument is flexible and depends on which type. Though in general it either represents a string to be read out, or an on screen element VoiceOver should shift its focus to.

Announcement Notification

When you need to share information that is related to an on screen update that you don't want to shift Accessibility Focus to you can just post an announcement.

post(.notificationType, "Success!");

Result: VoiceOver announces "Success!"

Use this diligently, but sparingly. Applications that share background updates with Voice Over users are appreciated. However, they can also interfere with more important announcements.

LayoutChanged Notification

Sometimes the element that currently has Accessibility Focus disappears from the Accessibility Tree because of a layout change. A simple example of this situation would be a modal dialog. Our content view hasn't changed, but an overlay requires the users attention.

If we needed to create a custom modal dialog then the following line of code would make sense:

post(.layoutChanged, modalTitle);

Result: Accessibility Focus shifts to the Title of the Modal Dialog.

A related Swift UI Concept is managed Accessibility Focus State.

Note: Technically you can also supply a String argument to layoutChanged notifications... though it has no additional behaviors from simply posting an announcement notification.

ScreenChanged Notification

If you were to decide to write your own custom navigation controller screenChanged notifications are something you would use a lot. These are for when the user is switching to a new major root view.

If you're writing semantic code screenChanged notifications should most often come from the Operating System/iOS Framework. In fact, you could argue the need to call this is a sign you could be relying on OS resources to do something that you are making very difficult for yourself.

Disclaimer shared! 😄

When dealing with this notification there is an important thing to note... you can provide a nil argument... and it in fact makes a lot of sense to do so in some situations.

Scenario: Nil Argument

Interestingly this is a valid line of code:

post(.screenChanged, nil);

Result: Beep Boop sound played. Invoke iOS Heuristic Engine to move focus.

When you supply a nil argument you do the same thing that iOS Navigation Controller code does for transitions. This initiates a heuristic algorithm within the iOS Framework to decide where the most sensible place to put Accessibility Focus is.

A nil screenChanged notification is a very useful tool for those looking to create their own custom navigation controllers and layouts.

Scenario: Not Nil Argument

Sometimes code gets messy. Whether it's a legacy navigation controller. A rogue bit of code in that iOS update. Or maybe you're just trying to do something custom and cool. Whenever you need to "pretend" like a new root View is being presented for the purposes of Assistive Technologies...

post(.screenChanged, viewToFocus);

Result: Beep Boop sound played. Accessibility Focus moves to the View.

Which would play the "beep boop" sound, shift focus to the viewToFocus, and then announce it.

Note: The only difference between a layoutChanged and a screenChanged notification is the "beep boop" sound. This is a really important bit of haptic feedback for VoiceOver users! It tells them that they are in a new Context and may need to familiarize themselves with it, especially if they aren't frequent application users.

Conclusion

In the event of context changes, it is important to send focus to a place that makes sense, or announce that such changes have taken place. Either approach is acceptable from an accessibility point of view in a lot of cases and which technique is better is user preference. When necessary you accomplish this by utilizing the notifications above. Consider your scenario and pick the one that makes the most sense!

Featured Posts

SwiftUI Design Systems

Device and Text Size

Applying WCAG 2.2

iOS Accessibility Test Plan