2

私はiPhoneゲームにアクセシビリティを追加し、UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification、@ "string")を多用して、ゲームで起こっているさまざまなことをアナウンスしています。99%の時間でうまく機能しますが、問題が1つあります。

すべての場合において、ナレーションのアナウンスは、アプリケーションデリゲートに追加した単一のメソッドから実行されます。

-(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];
            }
        }
    }
}

ゲームで次のイベントが発生する前にアナウンスが話されるように、遅延があります。アニメーションやその他のイベントでアナウンスが途切れる前に、アナウンス全体が確実に話されるようにするためのより良い方法を見つけることができませんでした。

1つを除くすべての場合で、このメソッドが呼び出されるとすぐにアナウンスが発声されます。あるケースでは、スピーキングが実行される前に約10秒の休止があります。この場合、コードをデバッグしてブレークポイントを設定し、UIAccessibilityPostNotification行を手動で実行しても、行は実行されますが、何も起こりません。それから10秒後、デバッガーで何もせずに、iPhoneはアナウンスを話し始めます。

この1つのアナウンスの唯一の特別な点は、それがtouchesEnded:UIScrollViewのイベントから呼び出されることです。その他のアナウンスはゲームループ全体の一部であり、タッチイベントに基づくものではありません。

ナレーションがアクセシビリティ通知をキューに入れ、すぐに話さない原因となる可能性があるアイデアはありますか?

よろしくお願いします、スティーブ

4

3 に答える 3

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. 
    } 
}
于 2013-04-04T07:05:08.670 に答える
2

dispatch_after遅延を渡してスリープ状態にする代わりに、アナウンスを話すためにこのメソッドを呼び出すたびに、次のイベントをトリガーするために遅延後に実行するブロックを同時にディスパッチできます。必要に応じて、ブロックを渡してこのメ​​ソッドに遅延させ、このメソッド内から後でディスパッチを送信することもできます。

于 2012-09-27T16:17:14.540 に答える
1

私のコメントを読んでください。これは、NSThread sleepForTimeInterval を使用した自発の問題です。これは悪い形だと何度も読んだことがありますが、アクセシビリティのナレーションのアナウンスのより良い解決策はまだ見当たりません. Apple が、この UIAccessibilityPostNotification 呼び出しに対してブロックを作成する (したがって、Objective-C メソッドも使用する) か、ナレーションが完了したときにコールバックすることを望みます。

于 2012-01-16T00:28:17.593 に答える