Jon Erickson
Jon Erickson

Reputation: 1976

iOS User location keeps snapping back

I have a map that when a button is pushed, it displays the user's location and zooms in. However, once that button is pushed, you cannot scroll on the map, it keeps snapping back to the user's location. What do I need to add/change? Thanks.

// Set action for when the refreh button is pressed

-(IBAction)refreshMapView:(id)sender {

[self refreshMap];
}

// Set action for when the show user location button is pressed

-(IBAction)getlocation {

mapView.showsUserLocation = YES;
[self.mapView.userLocation addObserver:self forKeyPath:@"location" options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) context:nil];

}

// Display segment button to change map views

-(IBAction)changeSeg:(id)sender {

if (segment.selectedSegmentIndex == 0) {
    mapView.mapType = MKMapTypeStandard;
}
if (segment.selectedSegmentIndex == 1) {
    mapView.mapType = MKMapTypeSatellite;
}
if (segment.selectedSegmentIndex == 2) {
    mapView.mapType = MKMapTypeHybrid;
}
}

// Listen to change in the userLocation

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{

MKCoordinateRegion region;
region.center = self.mapView.userLocation.coordinate;

MKCoordinateSpan span;
span.latitudeDelta  = 0.2; // Change these values to change the zoom
span.longitudeDelta = 0.2;
region.span = span;

[self.mapView setRegion:region animated:YES];
}   

// Load everying when map tab is accessed

-(void)viewDidLoad {

// Load mapView from MKMapKit

[super viewDidLoad];

mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
[self.view insertSubview:mapView atIndex:0];

[mapView setMapType:MKMapTypeStandard];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];
[mapView setDelegate:self];

// Display WCCCA HQ annotation pin.

MKCoordinateRegion WCCCA = { {0.0, 0.0} , {0.0, 0.0} };
WCCCA.center.latitude = 45.53540820864449;
WCCCA.center.longitude = -122.86178648471832;
WCCCA.span.longitudeDelta = 0.02f;
WCCCA.span.latitudeDelta = 0.02f;
[mapView setRegion:WCCCA animated:YES];

Annotation *ann1 = [[Annotation alloc] init];
ann1.title = @"WCCCA";
ann1.subtitle = @"Washington County Consolidated Communications Agency";
ann1.coordinate = WCCCA.center;
[mapView addAnnotation: ann1];

// Display call annotations based on xml parser data.

NSArray *callsArray = [xmlParser calls];

for (JointCAD *call in callsArray) {
    NSString *callnumber = [call.callnumber stringByAppendingFormat:@". "];
    NSString *callandnumber = [callnumber stringByAppendingString:call.currentCallType];
    Annotation *ann = [[Annotation alloc] init];
    ann.title = callandnumber;
    ann.subtitle = [call location];
    ann.coordinate = CLLocationCoordinate2DMake([call.latitude doubleValue], [call.longitude doubleValue]);
    [mapView addAnnotation:ann]; }

}

// Annotation details.

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {

// Set user location annotation to blue point instead of red pin

if ([annotation isKindOfClass:[MKUserLocation class]])
    return nil;

MKPinAnnotationView *MyPin=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"current"];
MyPin.pinColor = MKPinAnnotationColorRed;

UIButton *advertButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[advertButton addTarget:self action:@selector(button:) forControlEvents:UIControlEventTouchUpInside];

// MyPin.rightCalloutAccessoryView = advertButton;
MyPin.draggable = NO;
MyPin.highlighted = YES;
MyPin.animatesDrop= TRUE;
MyPin.canShowCallout = YES;

return MyPin;
}

 // Set default view when accessing Maps tab.

- (void)viewWillAppear:(BOOL)animated {

[super viewWillAppear:animated];

CLLocationCoordinate2D coord = {.latitude =  45.422424, .longitude =  -122.76};
MKCoordinateSpan span = {.latitudeDelta =  0.60, .longitudeDelta =  0.60};
MKCoordinateRegion region = {coord, span};
[mapView setRegion:region];
}

@end

Upvotes: 1

Views: 2535

Answers (1)

user467105
user467105

Reputation:

In the getlocation method you set showsUserLocation to YES and start observing changes to the user location using addObserver.

So whenever the user location changes (either when the device moves or an updated position is obtained), the observeValueForKeyPath method fires. In that method, you are resetting the map's region to center on the user location.

After the user pans or zooms somewhere else, if another user location change happens, that method will fire again and the map will go back to the user location.

The simplest fix in your case is to stop observing right after you zoom to the user location the first time. In the observeValueForKeyPath method, after the setRegion line, add:

[self.mapView.userLocation removeObserver:self forKeyPath:@"location"];


Note that since iOS 4.0, you don't need to use KVO (all that addObserver stuff) to observe user location changes. Instead, you could use the didUpdateUserLocation delegate method.

Since iOS 5.0, another option to zoom to the user location is to set the map view's userTrackingMode to MKUserTrackingModeFollow or MKUserTrackingModeFollowWithHeading. This way, you don't have to manually set the region. The map will zoom to and follow the user but still let the user then pan or zoom freely.

Upvotes: 3

Related Questions