determine if MKMapView was dragged/moved determine if MKMapView was dragged/moved ios ios

determine if MKMapView was dragged/moved


The code in the accepted answer fires when the region is changed for any reason. To properly detect a map drag you have to add a UIPanGestureRecognizer. Btw, this is the drag gesture recognizer (panning = dragging).

Step 1: Add the gesture recognizer in viewDidLoad:

-(void) viewDidLoad {    [super viewDidLoad];    UIPanGestureRecognizer* panRec = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didDragMap:)];    [panRec setDelegate:self];    [self.mapView addGestureRecognizer:panRec];}

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

@interface MapVC : UIViewController <UIGestureRecognizerDelegate, ...>

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

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {    return YES;}

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

- (void)didDragMap:(UIGestureRecognizer*)gestureRecognizer {    if (gestureRecognizer.state == UIGestureRecognizerStateEnded){        NSLog(@"drag ended");    }}


This is the only way that worked for me that detects pan as well as zoom changes initiated by user:

- (BOOL)mapViewRegionDidChangeFromUserInteraction{    UIView *view = self.mapView.subviews.firstObject;    //  Look through gesture recognizers to determine whether this region change is from user interaction    for(UIGestureRecognizer *recognizer in view.gestureRecognizers) {        if(recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateEnded) {            return YES;        }    }    return NO;}static BOOL mapChangedFromUserInteraction = NO;- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated{    mapChangedFromUserInteraction = [self mapViewRegionDidChangeFromUserInteraction];    if (mapChangedFromUserInteraction) {        // user changed map region    }}- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{    if (mapChangedFromUserInteraction) {        // user changed map region    }}


(Just the) Swift version of @mobi's excellent solution:

private var mapChangedFromUserInteraction = falseprivate func mapViewRegionDidChangeFromUserInteraction() -> Bool {    let view = self.mapView.subviews[0]    //  Look through gesture recognizers to determine whether this region change is from user interaction    if let gestureRecognizers = view.gestureRecognizers {        for recognizer in gestureRecognizers {            if( recognizer.state == UIGestureRecognizerState.Began || recognizer.state == UIGestureRecognizerState.Ended ) {                return true            }        }    }    return false}func mapView(mapView: MKMapView, regionWillChangeAnimated animated: Bool) {    mapChangedFromUserInteraction = mapViewRegionDidChangeFromUserInteraction()    if (mapChangedFromUserInteraction) {        // user changed map region    }}func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {    if (mapChangedFromUserInteraction) {        // user changed map region    }}