Search code examples
iosobjective-cmapkitmkannotationmkpointannotation

Storing Data in Annotation and Displaying on a Custom Callout but Data Changes to the Most Recent Update


So, I've created a custom callout that appears over the selected annotation. Everything works exactly how I want--the only problem is after I've dropped another pin of the same type, then all the past pins will display the same information. For example, I may have a pin drop that displays in the callout "McDonalds" and the next pin that drops displays "Starbucks". Now all my previously dropped pins will display "Starbucks".

I'm currently attempting to store information in the annotation's subtitle property and then displaying that through a formatted string onto my custom UIView's Label...It works but I need the annotation's information to never change. There must be something I'm missing or do not understand. Any help will be much appreciated.

I've posted all the code I believe to be relevant below. Thank you!

Custom Callout.h

#import <UIKit/UIKit.h>

@interface PinView : UIView
{
    UIView *view;
    UILabel *theValueLabel;
}

@property (nonatomic, retain) IBOutlet UIView *view;
@property (nonatomic, retain) IBOutlet UILabel *theValueLabel;

@end

Custom Callout.m

#import "PinView.h"

@implementation PinView
@synthesize theValueLabel;
@synthesize view;



- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        UIView *nib = [[[UINib nibWithNibName:@"customView" bundle:nil] instantiateWithOwner:self options:nil] objectAtIndex:0];
        [self addSubview:nib];
    }
    return self;
}


-(id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        if (self.subviews.count == 0) {
            UIView *nib = [[[UINib nibWithNibName:@"customView" bundle:nil] instantiateWithOwner:self options:nil] objectAtIndex:0];
            [self addSubview:nib];
        }
    }
    return self;
}

- (void)awakeFromNib {
    [super awakeFromNib];
    [self setup];
}

- (void)setup {
    self.theValueLabel.text = @"foo";
}

in my main View Controller.m

@interface BreadTrailViewController ()<CLLocationManagerDelegate, MKMapViewDelegate, MFMailComposeViewControllerDelegate>
{
    PinView *aView

    MKPointAnnotation *Pin1;
}

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    CLLocation *location = [locations lastObject];

    if (location != nil)
    {
         Pin1 = [[MKPointAnnotation alloc] init];
         Pin1.title = @"Venue";
         Pin1.subtitle = [NSString stringWithFormat:@"Venue Name: %@\n%f,%f\nAddress: %@",revGeocodeVenue, lat, lng, revGeocodeAddress];
         Pin1.coordinate = location.coordinate;
         [self.mapView addAnnotation:Pin1];
    }
}

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
    // If it's the user location, just return nil.
    if ([annotation isKindOfClass:[MKUserLocation class]])
        return nil;

    // Handle any custom annotations.
    if ([annotation isKindOfClass:[MKPointAnnotation class]])
    {
        MKPinAnnotationView *pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:@"CustomPinAnnotationView"];

        if (!pinView)
        {
            pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"CustomPinAnnotationView"];

            pinView.canShowCallout = NO;

        } else {

            pinView.annotation = annotation;
        }

        if ([[annotation title] containsString:@"Venue"])
        {
            pinView.pinTintColor = [UIColor greenColor];
        }

        return pinView;

    }
    return nil;

}

-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
    aView = [[PinView alloc] initWithFrame:CGRectMake( 0, 0, 300, 350)];

    aView.layer.cornerRadius = 20;
    aView.layer.masksToBounds = YES;
    aView.center = CGPointMake(view.bounds.size.width*0.5f, -aView.bounds.size.height*0.35f);

    //Using the Pin's subtitle to store the data string and display on PinView
    if ([[view.annotation title] containsString:@"Venue"])
    {
        aView.theValueLabel.text = Pin1.subtitle;
    }

    [view addSubview:aView];
}

-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
    [aView removeFromSuperview];
}

Solution

  • I found the problem! I was using Pin1.subtitle when what I should be using is view.annotation.subtitle--everything is working perfectly now. I hope this helps someone else!

    -(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
    {
        aView = [[PinView alloc] initWithFrame:CGRectMake( 0, 0, 300, 350)];
    
        aView.layer.cornerRadius = 20;
        aView.layer.masksToBounds = YES;
        aView.center = CGPointMake(view.bounds.size.width*0.5f, -aView.bounds.size.height*0.35f);
    
        //Using the Pin's subtitle to store the data string and display on PinView
        if ([[view.annotation title] containsString:@"Venue"])
        {
            aView.theValueLabel.text = view.annotation.subtitle;
        }
    
        [view addSubview:aView];
    }