3

I've created a custom annotation view by subclassing MKAnnotationView. This class also creates a custom callout (info pop-up 'bubble') view which is skinned to match my app.

I also want to be able to reskin the callout bubble for the user location dot, but it seems as though the only control I have over that view is whether it is overridden completely or not, by using the following inside the mapView:viewForAnnotation: method:

if(annotation == self.mapView.userLocation)
{
    return nil;
}

But what I really want to do is find out what annotation view MapKit is using for the user location blue dot, and then subclass it so I can skin its callout bubble... Or is there another way? Or just no way at all?

Pang
  • 9,564
  • 146
  • 81
  • 122
jowie
  • 8,028
  • 8
  • 55
  • 94

3 Answers3

1

I am not sure this will help you, but you can use the default user location annotation view, then steal the view in mapView:didSelectAnnotationView::

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
    if (view == [mapView viewForAnnotation:mapView.userLocation]) {
        // do what you want to 'view'
        // ...
    }
    // ...
}

I have used this trick to change the callout title and subtitle, and add an image using leftCalloutAccessoryView. However, I haven't tried totally replacing the callout, so I don't know if it's possible.

shawkinaw
  • 3,190
  • 2
  • 27
  • 30
  • That's a clever thought and I've given it a go, but the only problem is there doesn't seem to be a way of stopping the userLocation annotationView to stop showing its callout, even if I set it to NO. Any thoughts? – jowie Oct 28 '11 at 22:24
  • 1
    You also need to grab the annotation view in `mapView:didAddAnnotationViews:`. There, you can use the same test as above in the `if` statement, and set `canShowCallout` to `NO` there. – shawkinaw Oct 30 '11 at 18:50
  • That's brilliant thanks! Nearly there... I notice that the class of the object is MKUserLocationView. Is there any way of extending or subclassing MKUserLocationView to draw the new bubble, or will I have to build the code directly into the view controller? – jowie Oct 30 '11 at 21:58
  • That I'm not sure about. I do know that `MKUserLocationView` is private API, so subclassing it might not be desirable. Can you not do what you did with your other annotation view subclass? – shawkinaw Oct 31 '11 at 00:12
  • Do you know how? I can't subclass MKUserLocationView because as you say it is a private API, so I get the compiler error: "Semantic Issue: 'LMLUserLocationView' cannot use 'super' because it is a root class"... But I need to get the blue flashing dot and I don't get it if I just subclass MKAnnotationView :( – jowie Oct 31 '11 at 13:23
  • Right, you definitely need to keep the default MKUserLocationView. If you aren't able to muck around with it after it's been made and make the changes you need to, then the other option that comes to mind is making another, "ghost" annotation that is invisible but follows the user location annotation using key-value observing (if I recall correctly, `mapView:didUpdateUserLocation:` doesn't follow the blue dot precisely, but I may be wrong.) This "ghost" annotation's annotation view would then have your skinned callout. – shawkinaw Oct 31 '11 at 14:14
  • well I want to keep the blue dot animations because they include all the region circles etc... It's just the callout bubble I want to be able to change. So I guess my only option is to build the callout bubble animation within the view controller then! Thanks. – jowie Oct 31 '11 at 14:22
0

I think it is not possible directly, but you can override some methods in runtime with this: http://theocacao.com/document.page/266

k06a
  • 17,755
  • 10
  • 70
  • 110
0

You can use

if ([annotation isKindOfClass:[MKUserLocation class]]) { // or if(annotation == self.mapView.userLocation)
   MKAnnotationView * annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"MyLocation"];
   if (annotationView == nil) {
      annotationView = [[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"MyLocation"] autorelease];
         annotationView.canShowCallout = NO;
         annotationView.image = [UIImage imageNamedWithBrand:@"MyLocationPin.png"];
      } else {
         annotationView.annotation = annotation;
      }
   return annotationView;
}
Zoleas
  • 4,869
  • 1
  • 21
  • 33
  • That won't work, because it replaces the blue dot with the image "MyLocationPin.png". I want to be able to subclass the annotationView WITH the blue dot, so I can add a custom callout to it... Sorry. – jowie Oct 25 '11 at 10:02
  • Sorry, I didn't understand your question well. Well… I'm gonna think about your problem :) – Zoleas Oct 25 '11 at 10:26
  • thanks :) I'll see if I can reword it... Please feel free to edit it if it's not clear enough! – jowie Oct 25 '11 at 10:37