Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a pan gesture on to a MKMapView

EDIT : Will make it clearer what I am trying to achieve.

I have some annotations on a MKMapView that I want to make easy to drag. The standard Apple way to move the annotations is to tap once then quickly tap and hold and drag. The users of the app have complained that it is too difficult to do this.

So technically what I'd like to do is to use a pan gesture. The problem is that MKMapView is also using the pan gesture to move the map about.

What I would like to do is when the use does the pan gesture, check if the pan gesture starts really close to an annotation, if so then let the pan gesture handler move the annotation. I have this part working.

But if the pan gesture was not close to an annotation then pas the gesture on to MKMapView for it to be handled by it.

// EDIT END

I've a method to handle a pan gesture. This gets called as I would expect when there is a pan gesture on the MKMapView. Sometimes I would not want to handle the gesture in my method but to pass the gesture through to the MKMapView to pan/drag the map around like normal.

Here is an outline of what I've got so far. The pan gesture is being handled by the method:

-(void)panGesture:(UIPanGestureRecognizer*)sender

Depending on some logic I would like to pass this gesture through to the MKMapView (self.mapView). Can anybody share the code to do this please?

I tried [self.mapView gestureRecognizerShouldBegin:sender]; but nothing happened from this call.

- (void) addPanGesture
{
    self.panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGesture:)];
    self.panGesture.delegate = self;
    [self.panGesture setMinimumNumberOfTouches:1];
    [self.panGesture setMaximumNumberOfTouches:1];
    [self.mapView addGestureRecognizer:self.panGesture];

}

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

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    BOOL result = NO;
    if ((gestureRecognizer == self.panGesture) && [[otherGestureRecognizer view] isDescendantOfView:[gestureRecognizer view]])
    {
        result = YES;
    }
    return result;
}

-(void)panGesture:(UIPanGestureRecognizer*)sender
{
    //some logic to see if we will handle the gesture in this method or pass gesture on to the MKMapView

    return;
}
like image 215
Code Avatar asked Oct 29 '22 01:10

Code


2 Answers

The standard Apple way to move the annotations is to tap once then quickly tap and hold and drag. The users of the app have complained that it is too difficult to do this.

I'm not think so.. :(

I'm going to write my logic, Actually It is bad thing to use pan gesture even apple provide default drag and drop facility. BTW if you are going with your way that mentioned in your question then you must need to add separate pan gesture for each and every annotation those are displaying on the map. Add it's own tag and keep same name of gesture method for all so you will easily mange it by tag. so when end-user will tap/touch on any annotation then it's method will be called and you can get touched/tapped annotation by it's own tag. write your code for drag-drop annotation only. Not sure but might be solve your problem.

like image 59
iPatel Avatar answered Nov 15 '22 05:11

iPatel


I agree completely with iPatel: If possible one should use the standard Apple way, since users are used to it.
But if you really want to implement you own solution, maybe the following might work (not tested):

The MapView has a built-in PanGestureRecognizer (called here builInPGR). I assume you added your own PanGestureRecognizer (called here ownPGR) to this MapView.
Now the following function in the UIGestureRecognizerDelegate protocol controls if two gesture recognisers should recognise simultaneously (see the docs):

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, 
shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool

The default implementation returns false.

You mentioned that you can drag your annotations using ownPGR. This means that builInPGR does not recognise the pan gesture simultaneously with ownPGR.

If you implement now this delegate function and return true, ownPGR and builInPGR should work simultaneously: builInPGR would move the map, and ownPGR would check, if a region close to an annotation has been tapped, and if so, would move the annotation.

Now, this delegate function gives you also a pointer to builInPGR, the otherGestureRecognizer.
So if ownPGR decides to drag an annotation since it started close to it, you can set the property isEnabled of builInPGR to false. This lets builInPGR transition to a cancelled state, and the map would no longer be dragged.
Of course, you had to set builInPGR.isEnabled to true again, when ownPGR finishes dragging the annotation.

Once more: I don’t know if this works, but it might. And I strongly recommend to use the standard approach!

EDIT: I am sorry, I just realised that you wanted the answer in Obj-C. But, using the docs (just switch to Obj-C) it should be easy to test it in Obj-C.

like image 25
Reinhard Männer Avatar answered Nov 15 '22 05:11

Reinhard Männer