I'm trying to make macOS VoiceOver read some in text in the parent tabview when the child tabview changes tabs. VoiceOver always reads the first text entry in the child sub tab ignoring attempts to switch where the focus is.
I've tried these things, in the example textItem is a member of the parent tabview class:
<parent tabview>.setAccessibilityApplicationFocusedUIElement(textItem) <textItem>.setAccessibilityFocused(true)
Each sub tab is a view controller loaded from a storyboard and I've added code in viewDidAppear to set the accessibility focus. I've also tried using a notification to the parent tab view to set the accessibility focus at the end of the sub tab's viewDidAppear.
Nothing seems to work, is there way to actually change the current focused accessibility UI element programmatically? This needs to work on macOS 13 and greater.
Here is a rough layout of what I'm trying to accomplish. When the use selects "sub tab 2", I want the text "Text to read first" to be the focus and have VoiceOver read that. What really happens is VoiceOver reads the contents of the sub tab "Feature Name"
The problem I initially asked about is resolved but only for macOS 14 and higher, whereas I needed macOS 13 support.
If anyone else has this issue, the key was making the call in the tab view controller before switching to the sub tab view. The announcement is made and "Text to read first" is read and the "Feature Name" is read but only on macOS 14+.
I tried various UI elements for the the NSAccessibility.post() call, the sub tab view controller, the main tab view controller, the view containing both, the text field itself, and finally the main window, none resulted in the correct behavior.
if #available(macOS 14.0, *) {
AccessibilityNotification.ScreenChanged(self).post()
AccessibilityNotification.Announcement(textField.stringValue).post()
}
else {
// Fallback on earlier versions
NSAccessibility.post(element: NSApp.mainWindow as Any,
notification: .announcementRequested,
userInfo: [.announcement: textField.stringValue, .priority: NSAccessibilityPriorityLevel.high])
NSAccessibility.post(element: textField as Any, notification: .titleChanged)
}