在 VoiceOver 停止朗读文本后使用 AVSpeechSynthesizer 播报文本

Announce text using AVSpeechSynthesizer after VoiceOver stops speaking text

我需要在我的应用程序的所有用户执行某些操作时向他们通告一些文本。为此,我使用 AVSpeechSynthesizer。这很有效,除非您使用 VoiceOver 来执行操作。因为VoiceOver是在向用户播报一些系统提供的信息,然后我的AVSpeechUtterance同时播放,所以声音重叠了。如何将我的语音排入队列,以便在 VoiceOver 结束说话后才播放?

检查您的消息中的 VoiceOver 是否 运行 和 post UIAccessibilityAnnouncementNotification 而不是使用 AVSpeechSynthesizer.

您可以通过观察 VoiceOver 活动来实现。先添加画外音通知观察者:

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

然后,在指定的方法中:

-(void)voiceOverDidStop:(NSNotification*)n {
    NSString* msg;
    NSNumber* finished;

    msg = [[n userInfo] objectForKey:UIAccessibilityAnnouncementKeyStringValue];
    finished = [[n userInfo] objectForKey:UIAccessibilityAnnouncementKeyWasSuccessful];

    if(finished) {
        // send the AVSpeechSynthsizer message
    }
}

记得在处理您的应用程序之前删除观察!

您可以使用的另一种方法(如果适用)是编辑用户正在操作的对象的 accessibilityLabelaccessibilityHint 属性。将这些属性设置为 @"",以便 VoiceOver 知道关于该对象没有什么可说的。

希望这对您有所帮助,即使我的回答来得太晚了: )

我用 asyncAfter 完成了这个,代码是 SwiftUI,但我希望你能理解:

Button {
    if !UIAccessibility.isVoiceOverRunning {
        readOutLoud(translation)
    }
} label: {
    Image(systemName: "speaker.wave.3.fill")
}
.accessibilityElement()
.accessibilityLabel("Listen")
.accessibilityAction {
    DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
        readOutLoud(translation)
    })
}

当按下按钮且 VoiceOver 未激活时,该按钮会朗读文本。

激活 VoiceOver 后,将通过 accessibilityAction 以所需的延迟读取文本。