I would like to set the accessibility focus to the navigation bar's title item.
By default the focus is set from top left, meaning the back button would be on focus.
I would like the title item to be in focus.
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification,
navigationController?.navigationBar.items?.last)
Solution 1 I don't like it, but it was the minimum amount of hacking that does not rely on digging through hidden subviews (internal implementation of UINavigationBar view hierarchy).
First in viewWillAppear, I store a backup reference of the back button item, and then remove the back button item (leftBarButtonItem):
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
backButtonBackup = self.navigationItem.leftBarButtonItem
self.navigationItem.leftBarButtonItem = nil
}
Then I restore the back item, but only after I dispatch the screen changed event in viewDidAppear() :
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
self?.navigationItem.leftBarButtonItem = self?.backButtonBackup
}
}
Solution 2: Disable all accessibility on the nav bar and view controller up until viewDidAppear() is finished:
self.navigationController.navigationBar.accessibilityElementsHidden = true
self.view.accessibilityElementsHidden = true
, and then in viewDidAppear manually dispatching the layout element accessibility focused event to the label subview of UINavigationBar:
UIAccessibilityPostNotification( UIAccessibilityLayoutChangedNotification, self.navigationController.navigationBar.subviews[2].subviews[1])
// The label buried inside the nav bar. Not tested on all iOS versions.
// Alternately you can go digging for the label by checking class types.
// Then use DispatchAsync, to re-enable accessibility on the view and nav bar again...
I'm not a fan of this method either.
DispatchAsync delay in viewDidAppear seems to be needed in any case - and I think both solutions are still horrible.