Search code examples
ioscocos2d-iphoneuigesturerecognizer

held Touches are delayed in my game? UIGestureEnvironmentSortAndSendDelayedTouches?


I have an iOS cocos2d (v2) game in the app store that I had not updated for years, but recently discovered a bug and needed to fix it. This required me to go through all the pain of getting the app to build on a modern version of XCode. After I got it all working and am ready to submit my patch to the app store, I realized there is now a ridiculously slow lag in time when my app actually detects that the user has touched and held in place on the screen.

When looking at the call stack, if I quickly tap the screen everything works great, and my breakpoint is hit quickly:

enter image description here

But if I touch and hold down on the screen, there is almost a one second delay before my break point is even hit, and the call stack looks like: enter image description here

My question is, how do I turn off this behavior so that there are no delayed touches or calls to UIGestureEnvironmentSortAndSendDelayedTouches? In other words, I need touching and holding on the screen to fire the event immediately, exactly the same as it does when tapping quickly.

UPDATE

Here is the full stack trace:

 * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
     frame #0: 0x0000000100e79ab0 mygame`-[CCGLView touchesBegan:withEvent:](self=0x0000000102029c40, _cmd="touchesBegan:withEvent:", touches=0x0000000282f373c0, event=0x0000000281d62e20) at CCGLView.m:331
     frame #1: 0x00000001ca6aeaf0 UIKitCore`_UIGestureEnvironmentSortAndSendDelayedTouches + 4324
     frame #2: 0x00000001ca6a97ec UIKitCore`_UIGestureEnvironmentUpdate + 1236
     frame #3: 0x000000019d8896bc CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
     frame #4: 0x000000019d884350 CoreFoundation`__CFRunLoopDoObservers + 412
     frame #5: 0x000000019d8848f0 CoreFoundation`__CFRunLoopRun + 1264
     frame #6: 0x000000019d8840e0 CoreFoundation`CFRunLoopRunSpecific + 436
     frame #7: 0x000000019fafd584 GraphicsServices`GSEventRunModal + 100
   * frame #8: 0x00000001caa98c00 UIKitCore`UIApplicationMain + 212
     frame #9: 0x0000000100c7f8a4 mygame`main(argc=1, argv=0x000000016f2c77d8) at main.m:5
     frame #10: 0x000000019d342bb4 libdyld.dylib`start + 4

Solution

  • Turns out the best way I could solve this was to set the window's UIGestureRecognizer instance's delegate:

      # in app delegate: 
      CGRect frame = [[UIScreen mainScreen] bounds];
      UIWindow *window = [[UIWindow alloc] initWithFrame:frame];
      for (UIGestureRecognizer *gestureRecognizer in [window gestureRecognizers]) {
        gestureRecognizer.delegate = self;
      }
    

    and then implement the following methods on that delegate:

    -(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
        return NO;
    }
    
    -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
        return NO;
    }
    
    -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceivePress:(UIPress *)press {
        return NO;
    }