Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MapView detect scrolling

Tags:

ios

uiview

mapkit

I'm wishing that MKMapView inherited from UIScrollView just like UITableView and UICollectionView are. This way you can override the UIScrollView delegate methods and do what you need to do.

I've found the method of attaching a pan gesture to the MapView like so:

UIPanGestureRecognizer* mapPanGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(mapPanGestureHandler:)];
[mapPanGestureRecognizer setDelegate:self];
[self.mapView addGestureRecognizer:mapPanGestureRecognizer];

This works fairly well except for the fact that the mapView has a deceleration element to it. For example if you're in mid scroll and lift your finger, the map keeps going and slows down then eventually stops.

What I'm doing is rendering some offscreen annotations in an overlay on top of my map (another UIView) using core graphics. It's working great except for the deceleration problem.

All I need to know is that the map has moved. The parameters I need I can query straight from the map itself.

Has anyone found a technique to get callbacks while decelerating? I mean I suppose I could use a timer when the gesture ends to fire repeatedly for a half a second or so.

like image 989
VaporwareWolf Avatar asked Apr 16 '14 23:04

VaporwareWolf


1 Answers

MKMapView doesn't have analogous delegate callback to UIScrollView, so you're going to need to improvise.

Has anyone found a technique to get callbacks while decelerating? I mean I suppose I could use a timer when the gesture ends to fire repeatedly for a half a second or so.

If you're wanting to accurately keep views in sync with the map's movement, you'll be better off using CADisplayLink because you'll get a callback after each screen refresh. On the other hand, if you use a timer, the callbacks won't necessarily align with the refresh rate and you may see artifacts.

You'd set it up like this:

CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateViewsBasedOnMapRegion:)];
[link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];

And then handle the callback like this:

- (void)updateViewsBasedOnMapRegion:(CADisplayLink *)link
{
    // update whatever it is you need to update
}

You could use this exclusively and discard the gesture recognizer or keep the gesture recognizer and pause the link when not needed.

like image 63
Timothy Moose Avatar answered Sep 22 '22 19:09

Timothy Moose