Reputation: 33
The problem is that removing annotation disables custom annotation button for rightCalloutAccessoryView
.
When custom button is tapped, the protocol method mapView:annotationView:calloutAccessoryControlTapped
is called but sender method for custom button is not. Firstly added annotation to map works fine, the problem starts with initialization of second annotation.
Here is the code:
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBarText {
[searchBarText resignFirstResponder];
[self.searchTable dismissViewControllerAnimated:YES completion:nil];
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
//Geocoding search bar text (adress).
[geocoder geocodeAddressString:searchBarText.text completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
if (error) {
NSLog(@"Error with geocoding: %@", error);
} else {
//To remove previous annotation from MapView using its reference.
if (self.previousAnnotation != nil) {
[self.mapView removeAnnotation:self.previousAnnotation];
self.previousAnnotation = nil;
//To invoke result as the placemark object.
CLPlacemark *placemark = placemarks.firstObject;
//Adjusted region setup and data.
MKCoordinateRegion region = MKCoordinateRegionMake(placemark.location.coordinate, MKCoordinateSpanMake(0.01, 0.01));
MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:region];
[self.mapView setRegion:adjustedRegion animated:YES];
CustomAnnotation *customAnnotation = [[CustomAnnotation alloc] initWithTitle:placemark.name andLocation:CLLocationCoordinate2DMake(region.center.latitude, region.center.longitude)];
[self.mapView addAnnotation:customAnnotation];
//To save reference of newly added annotation.
self.previousAnnotation = customAnnotation;
} else if (self.previousAnnotation == nil) {
//To invoke result as the placemark object.
CLPlacemark *placemark = placemarks.firstObject;
//Adjusted region setup and data.
MKCoordinateRegion region = MKCoordinateRegionMake(placemark.location.coordinate, MKCoordinateSpanMake(0.01, 0.01));
MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:region];
[self.mapView setRegion:adjustedRegion animated:YES];
CustomAnnotation *customAnnotation = [[CustomAnnotation alloc] initWithTitle:placemark.name andLocation:CLLocationCoordinate2DMake(region.center.latitude, region.center.longitude)];
[self.mapView addAnnotation:customAnnotation];
//To save reference of newly added annotation.
self.previousAnnotation = customAnnotation;
}
}
}];
}
The logic seems fine. If I initialize annotations with the code below no problem occurs, I tap the button and button sender method is being called with every new annotation.
//To invoke result as the placemark object.
CLPlacemark *placemark = placemarks.firstObject;
//Adjusted region setup and data.
MKCoordinateRegion region = MKCoordinateRegionMake(placemark.location.coordinate, MKCoordinateSpanMake(0.01, 0.01));
MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:region];
[self.mapView setRegion:adjustedRegion animated:YES];
CustomAnnotation *customAnnotation = [[CustomAnnotation alloc] initWithTitle:placemark.name andLocation:CLLocationCoordinate2DMake(region.center.latitude, region.center.longitude)];
[self.mapView addAnnotation:customAnnotation];
Seems the problem exists between annotation removal and initialization of new annotation but I can't figure it out.
EDIT (more issue details)
From presenting second annotation on a map the callout button doesnt call it method (eventhough tap is detected). So for instance:
I search for adress1, I tap callout custom button, custom button method is called.
I search for adress2, adress1 callout bubble is correctly removed, new adress2 callout bubble appears on the map with correct coordinates, but custom button remains in selected state and tapping it doesnt call its method.
EDIT 2
Removal of annotations is correct (new one replaces old one, I checked it with logging self.mapView.annotations, also I checked placemark objects, with a new search the new location is the result).
Upvotes: 0
Views: 76
Reputation: 33
Ok, I figured it out.
The problem was that after annotation removal, annotation view is queued internally for later reuse (according to MKMapView class reference). All you need to do is to use dequeueReusableAnnotationViewWithIdentifier:
method after calling removeAnnotation:
.
if (self.previousAnnotation != nil) {
[self.mapView removeAnnotation:self.previousAnnotation];
//Set it nil before attaching it with new reference.
self.previousAnnotation = nil;
//To invoke result as the placemark object.
CLPlacemark *placemark = placemarks.firstObject;
//Adjusted region setup and data.
MKCoordinateRegion region = MKCoordinateRegionMake(placemark.location.coordinate, MKCoordinateSpanMake(0.01, 0.01));
MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:region];
[self.mapView setRegion:adjustedRegion animated:YES];
CustomAnnotation *customAnnotation = [[CustomAnnotation alloc] initWithTitle:placemark.name andLocation:CLLocationCoordinate2DMake(region.center.latitude, region.center.longitude)];
[self.mapView dequeueReusableAnnotationViewWithIdentifier:@"CustomAnnotation"];
[self.mapView addAnnotation:customAnnotation];
//To save reference of newly added annotation.
self.previousAnnotation = customAnnotation;
Upvotes: 0