UIAccessibilityAnnouncementNotification VoiceOver Interruption

7.8k views Asked by At

I'm having a great deal of trouble with iOS 7/8 UIAccessibility. The specific use case I am working with is what I would expect to be a pretty common "progress saved" use case.

EDIT: It has been brought to my attention that the desired outcome was not clear from my original question, so I've added a description here: The goal is for the "progress saved" message to be spoken via VoiceOver, either in lieu of the NavigationBar title being spoken, or after it has been spoken. I'm not sure what the typical behaviour is for accessibility in this case, so maybe someone familiar with iOS Accessibility can clarify this as well.

Starting from the simplest solution, and working towards the most complicated, I tried the following approaches.

-(void) showProgressSavedPanel {

    ... // present the panel toast
    NSString * message = NSLocalizedString(@"Your progress has been saved.", @"Progress saved message");
    UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, message);
}

Unfortunately, with this approach, the announcement is quickly interrupted by VoiceOver when it automatically speaks the navbar title followed by the title of the back button. The actual VoiceOver result is something like "Your progress has -- Navbar Title -- Back Button."

Reading on about iOS accessibility, I discovered a new API, which also does not seem to work. Having added a new IBOutlet pointing directly to the progress saved label, I replaced the code above with the following:

-(void) showProgressSavedPanel {

    ... // present the panel toast
    UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, _progressSavedLabel);
}

Using either UIAccessibilityScreenChangedNotification or UIAccessibilityLayoutChangedNotification had the same outcome: the expected message was not spoken whatsoever. No matter what I do it seems like VoiceOver just wants to speak the navbar title.

I have come up with a solution that makes me a very sad panda, which is to use the first solution except post the announcement notification after an arbitrary delay (1.5 seems to work), causing the announcement to occur after the back bar button item has been spoken.

Does anyone know of a better approach?

Thanks in advance :)

2

There are 2 answers

3
Justin On BEST ANSWER

You may not be able to achieve the desired effect with either API out-of-the-box. As you observed, the timing is a bit tricky, likely due to efforts VoiceOver, itself, is making to begin reading screen content after loading completes.

In my opinion, transient visible notifications like toast dialogs are best described using an announcement. You also want the announcement to voice after the user is told which screen they're on. While not ideal, you're right to consider posting the announcement after an artificial, hardcoded delay. Once implemented, experiment with different localizations to ensure it's consistently read after the title.

0
Nitin Vatsya On

Let the VoiceOver do it's primary task then post the Notification to announce the desired instruction with the help of "dispatch_after" execution block.

// Delay execution of my block for 2 seconds.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, @"desiredInstructionString"); });