Search code examples
swiftmacosaccessibilityappkitvoiceover

VoiceOver won't announce NSAccessibility Notification


I'm working to add accessibility to a custom UI element in an existing macOS codebase. We've got a custom error window that appears when an error occurs, and I'm trying to get VoiceOver to announce the error when it occurs.

Currently, I'm trying to use the NSAccessibility.post(element: Any, notification: NSAccessibility.Notification, userInfo: [NSAccessibility.NotificationUserInfoKey : Any]?) method, but while the code is run, the notification is not spoken.

Here's what I've currently got in my NSViewController:

NSAccessibility.post(element: self, notification: .announcementRequested, userInfo: [
    .announcement: NSLocalizedString("CANT_CONNECT_ERROR", comment: "Error string for connection failure"),
    .priority: NSAccessibilityPriorityLevel.high
])

My expectation was that, using the .announcementRequested option, VoiceOver should automatically pick this up and speak the announcement, but no luck. I've tried using different notification types, tried putting in a hardcoded string value in the .announcement argument, and tried using .rawValue and 90 for the .priority argument.


Solution

  • So I finally figured out how to get this to work after much trial and error (and danielpunkass's helpful comments). YMMV, but here's how I got it to work:

    1. The element argument has to be set to NSApp.mainWindow (I've added as Any as well to silence a compiler warning)
    2. The priority level in the userInfo dictionary has to be set using the .rawValue, not the actual enum value. Apple's documentation does not mention this of course.

    Here's my working code:

    NSAccessibility.post(
        element: NSApp.mainWindow as Any,
        notification: .announcementRequested,
        userInfo: [
            .announcement: "This is a custom accessibility notification",
            .priority: NSAccessibilityPriorityLevel.high.rawValue
        ]
    )