Mastering App Development and UIAccessibility with Swift: Adventure application

0 of 13 lessons complete (0%)


VoiceOver explanation screen

The iOS Accessibility Handbook

The VoiceOver explanation screen is intended to be presented modally when the player disables VoiceOver.

In AppCoordinator:

func start(window: UIWindow) {


selector: #selector(voiceOverStatusChanged),
name: UIAccessibility.voiceOverStatusDidChangeNotification, object: nil

) // 1

self.window = window navigationController.delegate = self

checkIfUserFirstStart() }

@objc internal func voiceOverStatusChanged() {

let isNonIntroViewController = !(self.lastNavigationControllerViewController is InstructionsViewController) let isVoiceOverRunning = EscapeFromBlindnessAccessibility.shared.isVoiceOverRunning // 2

if isNonIntroViewController && !isVoiceOverRunning { self.showActivateVoiceOverAlert()

} }


// 1: From any screen (after AppDelegate.applicationDidFinishLaunching(_:)), we subscribe to the UIAccessibility.voiceOverStatusDidChangeNotification. The selector method gets called whenever the VoiceOver status is changed by the user.

// 2: Under the hood, UIAccessibility.isVoiceOverRunning gets called and returns whether VoiceOver is enabled or not. If it is being disabled, we show our Voice Over explanation alert.

The actual alert behaves like this:

class VoiceOverAlertViewController: UIViewController, Coordinated { var coordinator: AppCoordinatorProtocol?

// MARK: – Outlets
@IBOutlet weak var voiceOverActivationInstructionsView: UIStackView! @IBOutlet weak var userCanContinueInstructionsView: UIStackView! @IBOutlet weak var continueButton: UIButton!

// MARK: – View Lifecycle
override func viewWillAppear(_ animated: Bool) {

super.viewWillAppear(animated) NotificationCenter.default.addObserver(

selector: #selector(voiceOverStatusChanged),
name: UIAccessibility.voiceOverStatusDidChangeNotification, object: nil

) }

override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) NotificationCenter.default.removeObserver(self)


// MARK: – Actions
@IBAction func onContinueButtonTouched() {

coordinator?.dismissActivateVoiceOverAlert() // 2 }

@objc internal func voiceOverStatusChanged() {
let isVoiceOverRunning = EscapeFromBlindnessAccessibility.shared.isVoiceOverRunning 

// 1
if isVoiceOverRunning {

self.voiceOverActivationInstructionsView.isHidden = true

self.userCanContinueInstructionsView.isHidden = false } else {

self.voiceOverActivationInstructionsView.isHidden = false

self.userCanContinueInstructionsView.isHidden = true }

} }

// 1: As for the app coordinator, we subscribe to the voiceOverStatusDidChangeNotification. If it is turned off, we show instructions on how to activate it.
When he turns in on, he can continue, we basically show a continue button.
// 2: when continue is selected, we dismiss the alert, coming back to the initial game context.