15

I am using custom call out (title and subtitle)for Current location icon. I tried following to disable default annotation but it does not work.

- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{
    NSLog(@"viewForAnnotation");
    if ([annotation isKindOfClass:[MKUserLocation class]])
    {
        MKAnnotationView *userLocationView = [mapView viewForAnnotation:annotation];
        userLocationView.canShowCallout = NO;
        NSLog(@"[annotation isKindOfClass:[MKUserLocation class]");
        return nil;
    }

}

Only way it works is

-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)ann
{
    if([ann.annotation isKindOfClass:[MKUserLocation class]] )
    {
       [mymap deselectAnnotation:ann.annotation animated:NO];
    }
}

But it lags sometimes. Is there other way do disable default callout view for current location annotation? Any help will be appreciated.

CodeBender
  • 35,668
  • 12
  • 125
  • 132
chatur
  • 2,365
  • 4
  • 24
  • 38

6 Answers6

28

To get this done one need to get reference of current location MKAnnotationView. One can get this reference anywhere but it is better to get it as soon as user location is determined.

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation 
{
 MKAnnotationView* annotationView = [mapView viewForAnnotation:userLocation];
annotationView.canShowCallout = NO;

}

Or use following method

 - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
MKAnnotationView *aV; 
     for (aV in views) {
            if ([aV.annotation isKindOfClass:[MKUserLocation class]]) {
                MKAnnotationView* annotationView = aV;
                 annotationView.canShowCallout = NO;

            }
    }

and if want to change in canShowCallout property in runtime then one can use following

for (AnnotationClass* annotation in mapView.annotations) 
    {
        if([annotation isKindOfClass:[MKUserLocation class]] )
        {
             MKAnnotationView* annotationView = [mapView viewForAnnotation:annotation];
             annotationView.canShowCallout = NO;
        }
    }
chatur
  • 2,365
  • 4
  • 24
  • 38
  • I found that the middle solution is not correct, because you iterate on views, therefore the class will be `MKUserLocationView` instead of `MKUserLocation`, which seems to be a private class. I recommend you to compare the inverse: you shall turn off `canShowCallout` when the annotation's class is NOT your own annotation's class (`MKAnnotation` for example). – gklka Jul 02 '13 at 19:03
  • 10
    This has stopped working in iOS7; the workaround (which also supports earlier versions) is to set `userLocation.title = @"";` in the method `mapView:didUpdateUserLocation` Setting the title to an empty string prevents the callout from appearing. – Carlos P Nov 07 '13 at 11:53
  • 1
    None of these methods worked well for me on iOS 7. The callout was disabled, but the blue dot was still selectable - you can tell if it overlaps with another map annotation. – joel.d Jan 10 '14 at 01:45
6

an update to this, using swift (based on chatur's answer):

func mapView(mapView: MKMapView!, didAddAnnotationViews views: [MKAnnotationView]!) {

    for view in views {
        if view.annotation.isKindOfClass(MKUserLocation) {
            view.canShowCallout = false
        }
    }

}

Note: using this, i did not require anything else to make it work

BananaAcid
  • 3,221
  • 35
  • 38
2

Swift:

This worked for me: Just add this delegate method.

func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
    for var view in views {
        view.canShowCallout = false
    }
}
Marius Kohmann
  • 713
  • 1
  • 8
  • 11
1

This worked for me on Swift 3.0 / iOS 10.

func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
    (views.filter { $0.isKind(of: MKUserLocation.self) }).first?.canShowCallout = false
}

Rather than loop through all the views, I just rely on the filter command, followed by the optional call on first since there should only be one location, and then set the value to false.

CodeBender
  • 35,668
  • 12
  • 125
  • 132
1
// Objective-C

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
        MKAnnotationView *userLocationView = [mapView viewForAnnotation:userLocation];   
        userLocationView.canShowCallout = NO;
}  

// Swift 4.2

func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
        let userAnnotationView = mapView.view(for: userLocation)
        userAnnotationView?.canShowCallout = false
}
Ivan Le Hjelmeland
  • 1,065
  • 11
  • 26
0

EDIT

Sorry for getting you wrong.

I banged my head on this.

This is the only way i have succeeded doing it. the problem with this method is that you have to change the UserLocation view. So it might be not so user friendly.

Any way:

 - (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation{
if ([annotation isKindOfClass:[MKUserLocation class]]){

        MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation                                                                           reuseIdentifier:nil];
        annotationView.image = [UIImage imageNamed:@"your-icon.png"];
        annotationView.enabled=NO;
         return annotationView;
    };
     ........}

Have to run to the kindergarden to take my kid :)

Good luck

shannoga
  • 19,649
  • 20
  • 104
  • 169
  • I just read your EDIT and thanks for your time. But in this way I will loose the accuracy animation of blue dot. If I find any better way I will let you know. – chatur Dec 09 '11 at 09:51
  • please see the answer posted by me. – chatur Jan 12 '12 at 09:50