使用UIAccessibilityPostNotification,画外音有很大的停顿

时间:2012-01-14 18:00:17

标签: iphone ios accessibility voiceover

我正在为iPhone游戏添加辅助功能,并广泛使用UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification,@“string”)来宣布游戏中发生的各种事情。它在99%的时间内运行良好,但我遇到了一个问题。

在所有情况下,配音公告都是通过我添加到应用程序代表的单一方法执行的。

- (void)voiceoverAction:(NSString *)speakString delay:(NSTimeInterval) delay {
    if (![[[[UIDevice currentDevice] systemVersion] substringToIndex:1] isEqualToString:@"3"]) {
        if (UIAccessibilityIsVoiceOverRunning()) {
            UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, speakString);
            if (delay > 0) {
                [NSThread sleepForTimeInterval:delay];
            }
        }
    }
}

延迟就在那里,所以在游戏中发生下一个事件之前会说出通知。我找不到一种更好的方法来确保在一些动画或其他事件切断之前发出整个公告。

在每种情况下,只有一个在调用此方法时立即说出通知。在一种情况下,在说话之前有大约10秒的暂停。在这种情况下,即使我调试代码并设置断点并手动执行UIAccessibilityPostNotification行,该行也会执行,但没有任何反应。然后10秒钟后,iPhone没有在调试器中做任何事情,iPhone就开始说出公告了。

关于这个公告的唯一特别之处在于它是从UIScrollView的touchesEnded:事件中调用的。其他公告是整个游戏循环的一部分,并非基于触摸事件。

知道什么可能导致画外音排队获取辅助功能通知而不是立即说出来吗?

提前致谢, 史蒂夫

3 个答案:

答案 0 :(得分:6)

如果您只支持iOS 6及其转发版,则可以使用UIAccessibilityAnnouncementDidFinishNotification确保在继续之前完成通知。

您会像任何其他通知一样观察它

// Observe announcementDidFinish to know when an announcment finishes
// and if it succuded or not. 
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(announcementFinished:)
                                             name:UIAccessibilityAnnouncementDidFinishNotification
                                           object:nil];

您收到的通知附带公告文本以及是否已阅读所有文本或公告是否已中止。如果您有多个公告,那么您可以等待正确的公告。

// When an announcement finishes this will get called.
- (void)announcementFinished:(NSNotification *)notification {
    // Get the text and if it succeded (read the entire thing) or not
    NSString *announcment = notification.userInfo[UIAccessibilityAnnouncementKeyStringValue];
    BOOL wasSuccessful = [notification.userInfo[UIAccessibilityAnnouncementKeyWasSuccessful] boolValue];

    if (wasSuccessful) {
        // The entire announcement was read, you can continue.
    } else {
        // The announcement was aborted by something else being read ...
        // Decide what you want to do in this case. 
    } 
}

答案 1 :(得分:2)

无论何时传递延迟并进行睡眠,只要您调用此方法说出您的通知,您就可以在使用dispatch_after延迟后调度块执行以触发您的下一个事件。如果您愿意,也可以传递块并延迟到此方法,并在此方法之后发送调度。

答案 2 :(得分:0)

阅读我的评论。这是使用NSThread sleepForTimeInterval的自我造成的问题。我已多次阅读这是不好的形式,但是我仍然没有看到更好的解决方案,可访问配音公告。我希望看到Apple为此UIAccessibilityPostNotification调用创建一个块(因此也使用Objective-C方法)或在完成配音时回调。