`touchesBegan:withEvent:` is delayed at left edge of screen
Asked Answered
P

5

6

I'm experiencing an issue where the first call to touchesBegan:withEvent: on a UIView or UIViewController is delayed when you touch on the left edge of the screen. This seems to be a new issue with iOS 10, and only happens on devices with 3D Touch (iPhone 6s and newer). In fact, if you disable 3D Touch in General->Accessibility, the issue goes away.

However, the issue doesn't seem to happen when you use UIGestureRecognizers. My workaround at the moment is to create a UIGestureRecognizer subclass that overrides the touches* methods and forwards them to my old implementation.

Is this just a bug or is there a way to get rid of the delay?

Posse answered 2/10, 2016 at 2:16 Comment(0)
P
7

try adding this to the viewdidappear method. this might fix the issue. it happened with me as well but i got this code from stack overflow that fixed my issue. hope it helps you too

let window = view.window!
let gr0 = window.gestureRecognizers![0] as UIGestureRecognizer
let gr1 = window.gestureRecognizers![1] as UIGestureRecognizer
gr0.delaysTouchesBegan = false
gr1.delaysTouchesBegan = false
Pilar answered 2/10, 2016 at 15:53 Comment(2)
Hm I see how that would solve the immediate issue but messing with the system gesture recognizers seems like it'll cause more problems down the linePosse
I did some more investigating and this seems like the best solution for now. These gestures recognizers are instances of _UISystemGestureGateGestureRecognizer and seem to be mainly used to make sure your app interacts nicer with system gestures like control center or 3D touch app switching. For the left edge, I believe the delay was added to prevent accidental app interaction when the user tries to switch apps, but in my case I need responsive touches on the left edge and it's alright if the touches trigger when the users tries to switch apps.Posse
B
3

Like danialias I'm working on a game. The solution I found (currently working, tested on an iPhone with 3D Touch enabled, where this was a real issue up to this point..) works for both games/apps:

It seems that UITapGestureRecognizer doesn't suffer from this delay, so simply add one to your view, and use it to handle taps.

In my game, I store touches and handle them on every interval update, so I overrode

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch

and there I stored the UITouch instance and returned NO.

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    [self.touches addObject:touch];
    return NO;
}
Bifocal answered 23/1, 2018 at 20:14 Comment(0)
N
1

Purteeek solution seems to work nicely in my case too. This is an objective-C implementation for SpriteKit:

- (void)didMoveToView:(SKView *)view {

    UIGestureRecognizer* gr0 = view.window.gestureRecognizers[0];
    UIGestureRecognizer* gr1 = view.window.gestureRecognizers[1];

    gr0.delaysTouchesBegan = false;
    gr1.delaysTouchesBegan = false;

}

This doesn't mess with other gesture recognizers, and the system 3D Touch still works fine. I wonder why this is not the default behavior.

Nondescript answered 27/3, 2017 at 4:30 Comment(0)
G
1

in iOS 13.2. it seems that trick is not possible:

[Warning] Trying to set delaysTouchesBegan to NO on a system gate gesture
recognizer - this is unsupported and will have undesired side effects

Looks like the only solution is disable 3D touch in Settings.

Gayelord answered 5/5, 2020 at 12:42 Comment(0)
S
1

This works for me

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    if let window = view.window,
        let recognizers = window.gestureRecognizers {
        recognizers.forEach { r in
            r.delaysTouchesBegan = false
            r.cancelsTouchesInView = false
            r.isEnabled = false
        }
    }
}
Sesterce answered 25/8, 2020 at 14:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.