4

I have set up a UILongPressGestureRecognizer that works fine in versions before IOS 13, but in this version to detect the second long press, I have to press twice.

That is to say:

1º LongPress -> Work Fine show "long tap"

2º LongPress -> Not work

3º LongPress -> Work Fine show "long tap"

4º LongPress -> Not work

...

This is my code.

    let longTapGesture = UILongPressGestureRecognizer(target: self, action: #selector(longTap))
    longTapGesture.delegate = self
    longTapGesture.numberOfTouchesRequired = 1
    longTapGesture.cancelsTouchesInView = false
    
    mapView.addGestureRecognizer(longTapGesture)

Function called is:

    @objc func longTap(sender: UIGestureRecognizer){
      print("long tap")
      .....
    }
ja12
  • 351
  • 2
  • 16
  • Hi, I have the same problem. Did you find a root cause and possibly the solution? – Dmytro Titov Jun 13 '23 at 11:25
  • @HangarRash My question is identical to the question above, no additional details. There's no point in duplicating questions - that's why I awarded existing question. – Dmytro Titov Jun 13 '23 at 17:38
  • @HangarRash, once I did like you suggested: created my own question with additional details - and it was closed as a duplicate. I don't want this to happen again :) I can add some details in the comment: I'm facing exactly the same behaviour with iOS 16.5 (not emulator - real device). I tried using different implementations for the delegate - all the same. I even tried omitting the delegate - didn't help either. If you have a working code sample - please, provide it as an answer and I'll accept it, if it works :) – Dmytro Titov Jun 13 '23 at 17:57
  • 1
    @DmytroTitov OK, I'm failing at reading today. I just now realized that this question is specific to adding the long press to a MKMapView. Sorry I wasted your time. I now also see this issue in one of my apps and didn't even realize it was an issue until I just tried it. I'm going to look into this and see if I can find a solution. – HangarRash Jun 13 '23 at 18:11

2 Answers2

2

The solution to this is to allow for simultaneous gestures. Simply set the long press gesture's delegate and implement the following delegate method:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}

That's it. The long press gesture on the map view will now work every time.

As a demonstration, create a new iOS project based on Swift and storyboard. Replace the provided ViewController.swift implementation with the following:

import UIKit
import MapKit

class ViewController: UIViewController {
    let mapView = MKMapView()

    override func viewDidLoad() {
        super.viewDidLoad()

        mapView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(mapView)

        NSLayoutConstraint.activate([
            mapView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            mapView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            mapView.topAnchor.constraint(equalTo: view.topAnchor),
            mapView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
        ])

        let lp = UILongPressGestureRecognizer(target: self, action: #selector(longPress))
        lp.delegate = self
        view.addGestureRecognizer(lp)
    }

    @objc func longPress(_ gesture: UILongPressGestureRecognizer) {
        switch gesture.state {
            case .began:
                print("began")
            case .ended:
                print("ended")
            case .changed:
                print("changed")
            case .cancelled:
                print("cancelled")
            default:
                print("other")
        }
    }
}

extension ViewController: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

Do note that shouldRecognizeSimultaneouslyWith will get called quite a few times. There seems to be at least 3 other gestures, including another long press gesture that expects two touches. So it's probably best not to setup your own long press gesture to require two touches.

HangarRash
  • 7,314
  • 5
  • 5
  • 32
  • It works! I don't know why it didn't, when I tried different combinations of implementing methods for the delegate. Thanks - I'll wait for a day, so that maybe OP could accept the answer. If not, I can start another bounty for accepting it. +1 anyway. – Dmytro Titov Jun 13 '23 at 19:31
0

In iOS 13, UILongPressGestureRecognizer only recognizes a single long press per touch. You could try to set "delaysTouchesBegan" to false.

Fox example:

let longTapGesture = UILongPressGestureRecognizer(target: self, action: #selector(longTap))
longTapGesture.delegate = self
longTapGesture.numberOfTouchesRequired = 1
longTapGesture.cancelsTouchesInView = false
longTapGesture.delaysTouchesBegan = false

mapView.addGestureRecognizer(longTapGesture)

Here is the resources I found: delaysTouchesBegan Doc

  • 1
    As shown the in the link to the docs you posted, `delaysTouchesBegan` defaults to `false` so your answer doesn't actually change anything. Do note that the question is not asking how to get more than one long press out of touch. The question is asking why only every other attempt at a long press on a MKMapView is working. – HangarRash Jun 13 '23 at 18:57