Search code examples
iosvoiceoveruiaccessibilityavspeechsynthesizer

Announce text using AVSpeechSynthesizer after VoiceOver stops speaking text


I need to announce some text to all users of my application when they perform some action. To do so I use AVSpeechSynthesizer. This works well, unless you use VoiceOver to perform the action. Because VoiceOver is announcing some system provided information to the user, then my AVSpeechUtterance is played at the same time, so the voices overlap. How can I queue up my speech utterance so that it isn't played until after VoiceOver finishes speaking?


Solution

  • You can achieve this by observing VoiceOver activities. First add a Voiceover notification observer:

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(voiceOverDidStop:) name:UIAccessibilityAnnouncementDidFinishNotification object:nil];
    

    Then, in the specified method:

    -(void)voiceOverDidStop:(NSNotification*)n {
        NSString* msg;
        NSNumber* finished;
    
        msg = [[n userInfo] objectForKey:UIAccessibilityAnnouncementKeyStringValue];
        finished = [[n userInfo] objectForKey:UIAccessibilityAnnouncementKeyWasSuccessful];
    
        if(finished) {
            // send the AVSpeechSynthsizer message
        }
    }
    

    Remember to remove the observe before disposing your app!

    Another method you can use (if applicable) is to edit the accessibilityLabel and accessibilityHint properties of the object the user is acting with. Set those properties to @"" so VoiceOver knows there is nothing to say about that object.

    Hope this helps you even if my answer came quite late : )