Will Ullrich
Will Ullrich

Reputation: 2228

Custom MapKit Annotation Lagging

I am display a simple MKMapView to display a collection of discovered places near the users location. Upon getting results, I am adding custom annotation views, let's say of class MyAnnotationView to the map.

These custom view's are displayed nicely, and I have ironed out all of the intricate handlers for a very nice UI. Like most would assume (or hope..), upon touching one of my markers, a separate (and custom) MKAnnotationView pops up to display more detail. This custom view has much more detail regarding the location found, with several buttons the user is able to interact with. The interaction is not the issue here (thankfully having overcome that obstacle).

My issue is, for whatever reason, there seems to be a bit of "lag" between the TouchDown and the TouchUpInside event calling, about roughly ~0.5 seconds delay to be more precise.

I have checked firing my anticipated method for only the TouchDown event, and it fires almost immediately (with the micro-delay any UIButton naturally creates).

My guess is that the MKMapView is the culprit. Given it is intercepting / monitoring many different UIGestureRecognizer's, I'm assuming the framework is just a bit "behind" in delivering my TouchUpInside event..

Unfortunately, assumptions don't really help anyone, especially if they don't come with a solution. So if anyone has any idea's / workarounds as to why the event handling is experiencing this delay I would love to hear. Thanks!

CODE REFERENCES

Here is some of my code to help:

Custom annotation view (w/ buttons) .h

#import <UIKit/UIKit.h>
#import "MyAnnotationView.h"
@import MapKit;

@interface MyAnnotationView : MKAnnotationView

.m

#import "MyAnnotationView.h"

@implementation MyAnnotationView {
    CGFloat width, height;
}

- (instancetype)initWithFrame:(CGRect)frame {
    
    if (self = [super initWithFrame:frame]) {
        
        width = frame.size.width, height = frame.size.height;
        
        self.contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
        [self addSubview:self.contentView];
        
    }
    
    return self;
    
}

Adding the views

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
    // Here I simply create an annotation, assign it to a new `MyAnnotationView`
    // and add the view.
    MyAnnotationView *view = [[MyAnnotationView alloc] init];
    ...

    // Note: the detailButton is just a UIButton

    // This lags...
    [view.detailButton addTarget:self action:@selector(didTouchCell) forControlEvents:UIControlEventTouchUpInside];

    // No lag... hmm
    // [view.detailButton addTarget:self action:@selector(didTouchCell) forControlEvents:UIControlEventTouchDown];


}

Upvotes: 1

Views: 488

Answers (1)

norders
norders

Reputation: 1252

The reason for the delay is that the map view is waiting to see if you're going to double-tap to zoom in. Even if you double-tap an annotation, the map will still zoom in. You can remove the delay if you're not bothered about double-tap-to-zoom by removing the double-tap gesture from the view hierarchy.

- (void)removeDoubleTapGestures:(UIView *)view {
    NSArray *gestureRecognizers = [view gestureRecognizers];

    for (UIGestureRecognizer *recognizer in gestureRecognizers) {
        if ([recognizer isKindOfClass:[UITapGestureRecognizer class]] &&
            [(UITapGestureRecognizer *)recognizer numberOfTapsRequired] == 2) {
                [view removeGestureRecognizer:recognizer];
        }
    }

    for (UIView *subview in view.subviews) {
        [self removeDoubleTapGestures:subview];
    }
}

In your viewDidLoad call:

[self removeDoubleTapGestures:myMapView];

Remember though that you're modifying MKMapView's view hierarchy, so if Apple change things in the future it could stop working.

Upvotes: 1

Related Questions