Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to continuously track the MKMapView region while scrolling/zooming?

I'd like to update my UI according to a MKMapView continuously when the user zooms or scrolls around the map. (Not only after the scrolling has ended, that works fine.)

I tried the delegate method mapView:regionWillChangeAnimated: which, according to the documentation, "is called whenever the currently displayed map region changes. During scrolling, this method may be called many times to report updates to the map position." https://developer.apple.com/documentation/mapkit/mkmapviewdelegate

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
    [self updateUIAcordingToMapViewRegionChange];
}

But unfortunately this doesn't work because the documentation seems not to be telling the truth. The method is only called once at the very beginning of the region change. During scrolling, while the finger is down and moving around, the method is never called again.

The only post about this problem I could find was by macrumors member namanhams: http://forums.macrumors.com/showthread.php?t=1225172 But nobody came up with any ideas...

As a workaround I tried setting up a timer in regionWillChange (and invalidate it in regionDidChange):

- (void)handleRegionChange:(NSTimer*)timer
{
   [self updateUIAcordingToMapViewRegionChange];
} 

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
    self.mapRegionIsChangingTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
                                                    target:self
                                                  selector:@selector(handleRegionChange:)
                                                  userInfo:nil
                                                   repeats:YES];
}

But that doesn't work, too. All method calls from the timer are executed all at once just after the scrolling has ended. Seems like scrolling the mapView is blocking the main thread or something…

I also read this post on stackoverflow, but unfortunately didn't completely understand it: Monitor MKMapView redraw events So if the solution to my problem lies indeed in that SO-thread, please tell me so, and I try to dig into it's details.

I still hope I'm simply too stupid or too blind to find the correct delegate method, and really appreciate any hints, workarounds and best practices to deal with MKMapView region tracking.

like image 605
Goodsquirrel Avatar asked May 29 '12 09:05

Goodsquirrel


1 Answers

This will work:

@interface MapViewController () {
    NSTimer *_updateUITimer;
}

@end

@implementation MapViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    _updateUITimer = [NSTimer timerWithTimeInterval:0.1 
                                             target:self 
                                           selector:@selector(updateUI) 
                                           userInfo:nil 
                                            repeats:YES];

    [[NSRunLoop mainRunLoop] addTimer:_updateUITimer forMode:NSRunLoopCommonModes];

}

- (void)dealloc
{
    [_updateUITimer invalidate];
}

- (void)updateUI
{
    // Update UI
}

@end

Another way is creating timer in mapView:regionWillChangeAnimated and invalidate it in mapView:regionDidChangeAnimated.

like image 139
AntonPalich Avatar answered Nov 16 '22 02:11

AntonPalich