5

How do I detect when the user has dragged or move an MKMapView in order to, e.g., prevent automatic homing in on the user's current location.

basicallydan
  • 2,134
  • 3
  • 25
  • 40

1 Answers1

18

Note: This answer was made possible and was adapted from Jano's response to the same question for Objective-C here: determine if MKMapView was dragged/moved. Thanks Jano.

To properly detect a map drag you have to add a UIPanGestureRecognizer. This is the drag gesture recognizer (panning = dragging).

Step 1: Add the gesture recognizer in viewDidLoad (Swift 2)

override func viewDidLoad() {
    super.viewDidLoad()
    // All your other setup code
    let mapDragRecognizer = UIPanGestureRecognizer(target: self, action: "didDragMap:")
    mapDragRecognizer.delegate = self
    self.mapView.addGestureRecognizer(mapDragRecognizer)
}

Swift 3 version of above gesture recognizer setup (selector syntax has changed)

override func viewDidLoad() {
    super.viewDidLoad()
    let mapDragRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.didDragMap(gestureRecognizer:)))
    mapDragRecognizer.delegate = self
    self.mapView.addGestureRecognizer(mapDragRecognizer)
}



Step 2: Add the protocol UIGestureRecognizerDelegate to the view controller so it works as delegate.

class MapViewController: UIViewController, UIGestureRecognizerDelegate

Step 3: Add the following code for the UIPanGestureRecognizer to work with the already existing gesture recognizers in MKMapView:

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

Step 4: In case you want to call your method once instead 50 times per drag, detect either the "drag ended" or "drag began" state in your selector:

func didDragMap(gestureRecognizer: UIGestureRecognizer) {
    if (gestureRecognizer.state == UIGestureRecognizerState.Began) {
        print("Map drag began")
    }

    if (gestureRecognizer.state == UIGestureRecognizerState.Ended) {
        print("Map drag ended")
    }
}

Hope this helps someone in need!

Community
  • 1
  • 1
basicallydan
  • 2,134
  • 3
  • 25
  • 40
  • What is the difference between this solution and using "regionDidChangeAnimated"? – lborgav May 04 '16 at 20:05
  • 1
    how do i go about using step 4 I cant get the func to be called – SwiftER Dec 20 '16 at 21:59
  • 1
    @pprevalon - `didDragMap()` is triggered by the mapDragRecognizer's selector. It is probably not being called for you because the syntax for this keeps changing in swift - in swift 3 for example the gesture recognizer would need to be set up like this to trigger the didDragMap function. `let mapPanInteractionRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.didDragMap(gestureRecognizer:)))`. – Natalia Jan 12 '17 at 00:09