Customize map annotations loaded from plist

Discussion in 'iOS Programming' started by SimonBS, Feb 10, 2011.

  1. SimonBS, Feb 10, 2011
    Last edited: Feb 10, 2011

    SimonBS macrumors regular

    SimonBS

    Joined:
    Dec 30, 2009
    #1
    Hi,

    I found a short guide on how to load "annotation data" from a plist and add those annotations (pins) to a MapView.

    My question is if anyone can tell me how I would customize the pins the most easily? As an example, I would like to define a color and an image in the plist and then have it set when adding the pins.

    The pins are added like this:

    MyAnnotation.m:

    Code:
    @implementation MyAnnotation
    @synthesize title, subtitle, coordinate;
    
    -(void) dealloc {
        [super dealloc];
        self.title = nil;
        self.subtitle = nil;
    }
    
    MyAnnotation.h

    Code:
    #import <Foundation/Foundation.h>
    #import <MapKit/MapKit.h>
    
    @interface MyAnnotation : NSObject<MKAnnotation> {
        CLLocationCoordinate2D coordinate;
        NSString *title;
        NSString *subtitle;
    }
    
    @property (nonatomic, assign) CLLocationCoordinate2D coordinate;
    @property (nonatomic, copy) NSString* title;
    @property (nonatomic, copy) NSString* subtitle;
    Running through the plist in ViewDidLoad in MapViewController.m (array containg dictionaries for each pin) and adding annotations.

    Code:
    NSString *path = [[NSBundle mainBundle] pathForResource:@"Annotations" ofType:@"plist"];
        NSMutableArray* anns = [[NSMutableArray alloc] initWithContentsOfFile:path];
    
        for(int i = 0; i < [anns count]; i++) {
            float realLatitude = [[[anns objectAtIndex:i] objectForKey:@"latitude"] floatValue];
            float realLongitude = [[[anns objectAtIndex:i] objectForKey:@"longitude"] floatValue];
    
            MyAnnotation* myAnnotation = [[MyAnnotation alloc] init];
            CLLocationCoordinate2D theCoordinate;
            theCoordinate.latitude = realLatitude;
            theCoordinate.longitude = realLongitude;
            myAnnotation.coordinate = theCoordinate;
            myAnnotation.title = [[anns objectAtIndex:i] objectForKey:@"title"];
            myAnnotation.subtitle = [[anns objectAtIndex:i] objectForKey:@"subtitle"];
            [mapView addAnnotation:myAnnotation];
            [annotations addObject:myAnnotation];
            [myAnnotation release];
        }
    EDIT:
    I have added the viewForAnnotation method which sets the color but how can I set the color of each pin individually?

    Code:
    -(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation {
    	MKPinAnnotationView *pinView = nil;
    	
    	if(annotation != mapView.userLocation) {
    		static NSString *defaultPinID = @"com.invasivecode.pin";
    		pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
    		if ( pinView == nil ) pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
    		
    		pinView.pinColor = MKPinAnnotationColorPurple; 
    		pinView.canShowCallout = YES;
    		pinView.animatesDrop = YES;
    	} 
    	else {
    		[mapView.userLocation setTitle:@"I am here"];
    	}
    	
    	return pinView;
    }
     
  2. SimonBS thread starter macrumors regular

    SimonBS

    Joined:
    Dec 30, 2009
    #2
    I have added the viewForAnnotation method which sets the color but how can I set the color of each pin individually?
     
  3. cnstoll macrumors 6502

    Joined:
    Aug 29, 2010
    #3
    I believe you would do that in the viewForAnnotation method.... You are certainly allowed to return different MKAnnotationViews (with different colors) based on the annotation that you receive.
     
  4. SimonBS thread starter macrumors regular

    SimonBS

    Joined:
    Dec 30, 2009
    #4
    I just can't seem to find out how to "send the color" to viewForAnnotation and not hardcode it directly into the method.
     
  5. cnstoll macrumors 6502

    Joined:
    Aug 29, 2010
    #5
    You could make a helper method that you'd call from viewForAnnotation and pass it the annotation and have it return a color for that annotation.
     
  6. nickculbertson macrumors regular

    nickculbertson

    Joined:
    Nov 19, 2010
    Location:
    Nashville, TN
    #6
    Not sure if this helps since you are using the plist but... In the apple demo "MapCallouts" they color the pins by
    Code:
    - (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation
    {
        // if it's the user location, just return nil.
        if ([annotation isKindOfClass:[MKUserLocation class]])
            return nil;
        
        // handle our two custom annotations
        //
        if ([annotation isKindOfClass:[BridgeAnnotation class]]) // for Golden Gate Bridge
        {
            // try to dequeue an existing pin view first
            static NSString* BridgeAnnotationIdentifier = @"bridgeAnnotationIdentifier";
            MKPinAnnotationView* pinView = (MKPinAnnotationView *)
                                            [mapView dequeueReusableAnnotationViewWithIdentifier:BridgeAnnotationIdentifier];
            if (!pinView)
            {
                // if an existing pin view was not available, create one
                MKPinAnnotationView* customPinView = [[[MKPinAnnotationView alloc]
                                                 initWithAnnotation:annotation reuseIdentifier:BridgeAnnotationIdentifier] autorelease];
                [B]customPinView.pinColor = MKPinAnnotationColorPurple;[/B]
                customPinView.animatesDrop = YES;
                customPinView.canShowCallout = YES;
                
                // add a detail disclosure button to the callout which will open a new view controller page
                //
                // note: you can assign a specific call out accessory view, or as MKMapViewDelegate you can implement:
                //  - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control;
                //
                UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
                [rightButton addTarget:self
                                action:@selector(showDetails:)
                      forControlEvents:UIControlEventTouchUpInside];
                customPinView.rightCalloutAccessoryView = rightButton;
    
                return customPinView;
            }
            else
            {
                pinView.annotation = annotation;
            }
            return pinView;
        }
        
        return nil;
    }
    
     
  7. SimonBS thread starter macrumors regular

    SimonBS

    Joined:
    Dec 30, 2009
    #7
    Problem is that Apple is assigning ALL annotations with the same color - I would like to be able to have some annotations in green, some in red and some in purple.
     
  8. SimonBS thread starter macrumors regular

    SimonBS

    Joined:
    Dec 30, 2009
    #8
    Solved! It can be done like this:

    Code:
    for(MyAnnotation* a in mapView.annotations) {
    			if(annotation == a && annotation != mapView.userLocation) {
    				pinView.image = [UIImage imageNamed:a.annImage];
    			}
    		}
     

Share This Page