0

I'm working on an application that uses custom AnnotationViews. It has a custom image and an background with a label in it. The background and label are subViews of the annotationView.

if ([annotation isKindOfClass:[VehicleAnnotation class]]) {
    VehicleAnnotation *vehicleAnnotation = annotation;

    MKPinAnnotationView *pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:driverAnnotationIdentifier];
    if(!pinView)
    {
        pinView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:driverAnnotationIdentifier];
    }

    pinView.annotation = annotation;

    pinView.canShowCallout = NO;
    pinView.image = [ImageHelper imageForStatus:vehicleAnnotation.vehicle.driver.driverStatus];

    // Add a label with the name of the driver
    CGRect pinFrame = pinView.frame;
    UILabel *label = [[UILabel alloc] init];
    [label setBackgroundColor:[UIColor clearColor]];
    [label setTextColor:[UIColor whiteColor]];
    [label setNumberOfLines:2];
    [label setLineBreakMode:NSLineBreakByWordWrapping];
    [label setFont:[UIFont systemFontOfSize:12]];
    label.text = vehicleAnnotation.vehicle.driver.description;

    CGSize maximumSize = CGSizeMake(100, 50);
    CGSize myStringSize = [label.text sizeWithFont:label.font
                                 constrainedToSize:maximumSize
                                     lineBreakMode:label.lineBreakMode];

    CGRect labelFrame = CGRectMake(pinFrame.origin.x, pinFrame.origin.y + pinFrame.size.height * 2 + 2, myStringSize.width, myStringSize.height);
    [label setFrame:labelFrame];

    // Add a background to the label.
    CGFloat offset = 5;
    CGRect backgroundFrame = CGRectMake(labelFrame.origin.x - offset, labelFrame.origin.y - offset , labelFrame.size.width + 2 * offset, labelFrame.size.height + 2 * offset);
    UIView *backgroundView = [[UIView alloc] initWithFrame:backgroundFrame];
    backgroundView.layer.cornerRadius = 5;
    backgroundView.layer.masksToBounds = YES;
    [backgroundView setBackgroundColor:[UIColor darkGrayColor]];
    [backgroundView setAlpha:0.8];
    [pinView addSubview:backgroundView];

    [label setUserInteractionEnabled:YES];
    [label setMultipleTouchEnabled:YES];
    [pinView addSubview:label];

    return pinView;
}

This code is performed each time new positions are received. The problem is that the old label and old background are still there. So I tought i put this code:

MKPinAnnotationView *pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:driverAnnotationIdentifier];
if(!pinView)
{
    pinView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:driverAnnotationIdentifier];
}
for(UIView *view in [pinView subviews])
{
    [view removeFromSuperview];
}
pinView.annotation = annotation;

But then no label or background is shown. Can somebody help me to replace or remove in a proper way the background and label?

Thank you!

Rob
  • 415,655
  • 72
  • 787
  • 1,044
Michael90
  • 367
  • 3
  • 15

2 Answers2

2

I suggest to make your own custom MKAnnotatinView. Otherwise using the above code, try adding Label and background view inside the bock in which you alloc init the MKAnnotationView. Set the frame and text and other properties which change for different annotations outside the block like below.

if ([annotation isKindOfClass:[VehicleAnnotation class]]) {
    VehicleAnnotation *vehicleAnnotation = annotation;

    MKPinAnnotationView *pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:driverAnnotationIdentifier];
    if(!pinView)
    {
        pinView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:driverAnnotationIdentifier];
    UILabel *label = [[UILabel alloc] init];
    [label setBackgroundColor:[UIColor clearColor]];
    [label setTextColor:[UIColor whiteColor]];
    [label setNumberOfLines:2];
    [label setLineBreakMode:NSLineBreakByWordWrapping];
    [label setFont:[UIFont systemFontOfSize:12]];
    [label setUserInteractionEnabled:YES];
    [label setMultipleTouchEnabled:YES];
    [label setTag:101];

    UIView *backgroundView = [[UIView alloc]init];
    [backgroundView setTag:102];
    backgroundView.layer.cornerRadius = 5;
    backgroundView.layer.masksToBounds = YES;
    [backgroundView setBackgroundColor:[UIColor darkGrayColor]];
    [backgroundView setAlpha:0.8];
    [pinView addSubView:backgroundView];
    [pinView addSubview:label];



    }

    pinView.annotation = annotation;

    pinView.canShowCallout = NO;
    pinView.image = [ImageHelper imageForStatus:vehicleAnnotation.vehicle.driver.driverStatus];

    // set frame of Label
    CGRect pinFrame = pinView.frame;
   UILabel *label = (UILabel *)[pinView viewWithTag:101];
    label.text = vehicleAnnotation.vehicle.driver.description;

    CGSize maximumSize = CGSizeMake(100, 50);
    CGSize myStringSize = [label.text sizeWithFont:label.font
                                 constrainedToSize:maximumSize
                                     lineBreakMode:label.lineBreakMode];

    CGRect labelFrame = CGRectMake(pinFrame.origin.x, pinFrame.origin.y + pinFrame.size.height * 2 + 2, myStringSize.width, myStringSize.height);
    [label setFrame:labelFrame];

    // set backgroundView frame.
    CGFloat offset = 5;
    CGRect backgroundFrame = CGRectMake(labelFrame.origin.x - offset, labelFrame.origin.y - offset , labelFrame.size.width + 2 * offset, labelFrame.size.height + 2 * offset);
    UIView *backgroundView = [pinView viewWithTag:102];
    [backgroundView setFrame:backgroundFrame];

    return pinView;
}
Vishal Singh
  • 4,400
  • 4
  • 27
  • 43
  • The same thing keeps happening with this code. When it's initiated, it shows the background(without the label...) and on an update the background isnt't shown anymore. I guess the only solution would be a custom MKPinAnnotationView – Michael90 Sep 03 '13 at 07:06
  • Yes sorry I added label as subview first and than backgroundView. i have fixed the code, check if this helps otherwise custom annotation is your answer.@Michael90 – Vishal Singh Sep 03 '13 at 08:02
  • The label shows correct now, but both the label and background disappear after an update. I will mark you answer as accepted because I believe a custom annotation is the way to go. – Michael90 Sep 03 '13 at 09:12
1

Setting the image of an MKPinAnnotationView is ineffective, it will overwrite it. Use a regular MKAnnotationView.

Also search on Stackocerflow, this question was asked and answered just six hours before you asked it. MapView Custom Pin Image Issue

Community
  • 1
  • 1
Craig
  • 8,093
  • 8
  • 42
  • 74
  • This wasn't about the image, this is about adding a subview and updating it – Michael90 Sep 03 '13 at 06:56
  • The 12th line of your code attempts to set the image of an MKPinAnnotationView. I suspect they are related. Essentially the MKPinAnnotationView looks how Apple want it to look, if you want something else then you should subclass MKAnnotationView. – Craig Sep 03 '13 at 07:33