web-dev-qa-db-ja.com

UIViewController touchesBegan、touchesMoved、touchesEndedが、2つのタッチの最初のタッチが開始、移動、または終了したときにのみ呼び出されるのはなぜですか?

UIViewControllerのtouchesBegan/Moved/Endedメソッドを介した複数のタッチの処理に問題があります。 cocos2dアプリ(ccTouchesBegan/Moved/Endedを使用)でも同じ動作が見られるので、この質問はiOSのすべてのタッチ処理に適用できると思います。使用しているコードを以下に示し、その後に表示されている結果を示します。

すべてのメソッドはUIViewControllerサブクラスに実装されています。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"Touches Began");
    [self logTouchesFor: event];

    [super touchesEnded: touches withEvent: event];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"Touches Moved");
    [self logTouchesFor: event];

    [super touchesEnded: touches withEvent: event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"Touches Ended");
    [self logTouchesFor: event];

    [super touchesEnded: touches withEvent: event];
}

-(void)logTouchesFor:(UIEvent *)event
{
    int count = 1;

    for (UITouch *touch in event.allTouches)
    {
        CGPoint location = [touch locationInView: self.view];

        NSLog(@"%d: (%.0f, %.0f)", count, location.x, location.y);
        count++;
    }
}

興味深い結果が得られました...

シングルタッチは期待どおりに機能します

親指で画面に触れたとしましょう。出力ウィンドウに、touchesBeganが期待どおりに呼び出されていることがわかります。親指を動かしてtouchesMovedが呼び出されます。次に、親指を画面から離すと、touchesEndedが呼び出されます。これはすべて予想どおりです。ビューコントローラーがタッチイベントを受信して​​いて、どこでもvc.view.userInteractionEnabled = YESを見逃していないことを明確にするために、これをコントロールケースとして質問に含めています。

セカンドタッチはtouchsBegin、touchesMoved、touchsEndedを引き起こしません

これは最も興味深いものです。親指で画面に触れ(touchesBeganと呼ばれます)、画面上で静止させたとします。次に、親指を同じ場所に置いたまま、人差し指で画面の別の場所に触れます。 TouchesBeganは呼び出されません。次に、親指を完全に動かさずに人差し指を動かしたとしましょう(これは難しい場合がありますが、可能です)。 TouchesMovedは呼び出されません。次に、人差し指を画面から離します。 TouchesEndedは呼び出されません。最後に、親指を動かしてtouchesMovedが呼び出されます。次に、画面から親指を離すと、touchesEndedが呼び出されます。

明確にするために、viewDidLoadメソッドにself.view.multipleTouchEnabled = YESを設定しました。

セカンドタッチに関する情報が利用可能で、ファーストタッチの動きを提供します

今回は、すぐ上の例と非常によく似た処理を行います。親指で画面に触れてから、親指を動かさずに人差し指を動かします。 TouchesBeganは、親指が画面に当たったときに呼び出されますが、人差し指は呼び出されません。親指を動かすと、touchesMovedが呼び出されます。それだけでなく、event.allTouches配列には2つのタッチがあります(そうです、2番目のタッチは私が期待する場所です)。これは、システムが2回目に画面に触れたことを認識しているが、ViewControllerのタッチ処理方法を通じて通知されていないことを意味します。

セカンドタッチの変更について通知するにはどうすればよいですか?

ファーストタッチも変わったときではなく、セカンドタッチの場所や状態の変化に対応できるようにしたいと思っています。片方のタッチをもう一方のタッチに影響を与えずに変更するのは非常に難しいため、多くの場合、これは問題にはなりませんが、問題になる可能性のある状況が少なくとも1つあります。明らかな何かが欠けていますか?他の誰かがこの動作に気づいたか、問題がありましたか?

関連する場合は、iOS5.1を実行しているiPhone3GSを使用しています。

10
rankAmateur

さて、私はプロジェクトを丹念に再構築し、ファイルを1つずつ追加し始めましたが、それはわかったと思います...

問題のビューのサブビューがあり、userInteractionEnabled == YES。これをNOに設定すると、ビューコントローラーはタッチごとにtouchesBegan/Moved/Ended呼び出しを取得し始めました。おそらく、2番目のタッチはサブビューによって要求され、ビューコントローラに到達していませんでしたが、なぜこれが最初のタッチではなく2番目のタッチでのみ発生するのかわかりません。

Cocos2dプロジェクトで何が起こっているのかはまだわかりませんが、同じことを実行できるサブビューやノードがないため、おそらく別の問題です。

11
rankAmateur