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.
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.