I used the CLLocationManager delegate update methods to get the current location about every second, keeping the previous location and interpolating between them. This is a bit more effort, but t makes tracking a lot smoother. Here is my code:
#define zoomSpan MKCoordinateSpanMake(0.001f, 0.001f) @property (strong, nonatomic) CLLocation *lastLocation; @property (strong, nonatomic) MKMapView *mapView; @property (strong, nonatomic) CLLocationManager *locationManager; ... - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { CLLocation *currentLocation = locations[locations.count - 1]; // Set to last location, for faster setting to correct position [self.mapView setRegion:MKCoordinateRegionMake(self.lastLocation.coordinate, zoomSpan) animated:NO]; // Locations in-between coordinates for smooth tracking CLLocationDegrees deltaLat = currentLocation.coordinate.latitude - self.lastLocation.coordinate.latitude; CLLocationDegrees deltaLon = currentLocation.coordinate.longitude - self.lastLocation.coordinate.longitude; NSArray *locationsArray = @[[[CLLocation alloc] initWithLatitude:(self.lastLocation.coordinate.latitude + deltaLat * 0.2) longitude:(self.lastLocation.coordinate.longitude + deltaLon * 0.2)], [[CLLocation alloc] initWithLatitude:(self.lastLocation.coordinate.latitude + deltaLat * 0.4) longitude:(self.lastLocation.coordinate.longitude + deltaLon * 0.4)], [[CLLocation alloc] initWithLatitude:(self.lastLocation.coordinate.latitude + deltaLat * 0.6) longitude:(self.lastLocation.coordinate.longitude + deltaLon * 0.6)], [[CLLocation alloc] initWithLatitude:(self.lastLocation.coordinate.latitude + deltaLat * 0.8) longitude:(self.lastLocation.coordinate.longitude + deltaLon * 0.8)], currentLocation]; float timer = 0; for (CLLocation *nextLocation in locationsArray) { [self performSelector:@selector(updateMapCenterLocation:) withObject:nextLocation afterDelay:timer]; timer += 0.2; } self.lastLocation = currentLocation; } - (void)updateMapCenterLocation:(CLLocation *)location { [self.mapView setRegion:MKCoordinateRegionMake(location.coordinate, zoomSpan) animated:YES]; }
Make sure that the class in which you use it (usually a view controller that contains the map view) is set to the CLLocationManager delegate and implements the CLLocationManagerDelegate protocol.
Some additional comments:
- The behavior of this code is similar to
MKUserTracking , but it does not support custom zoom levels. There seems to be a bug that returns the zoom level when starting tracking, so this is a workaround. zoomSpan is currently fixed, but you can also use the range of the current area with self.mapView.region.span .
checkbutton
source share