选择注释引脚时更改引脚颜色

时间:2013-09-10 00:48:27

标签: ios mkmapview

我的应用程序是一个地图视图,用户可以在其中输入一个地址,该地址将在总帐的地图上放置一个紫色图钉。其次,用户可以输入任何地址,这将在地图上放置一个红色图钉。我希望能够将红色引脚的引脚颜色更改为红色,绿色或紫色。

我偶然发现了一个教程,该教程允许用户选择注释引脚并通过显示模态视图来更改其引脚颜色。我仔细地按照教程,但由于某种原因,它无法正常工作。显示带有引脚选择的模态视图,但是当选择引脚颜色时,地图视图上的引脚颜色不会更新。此外,我不想使用“png”图像来显示自定义引脚,而是使用内置标准引脚(因为这就是我所需要的)。我如何调整下面的代码来实现这一目标?我添加了我的整个代码。

FieldMapController.m

#import "FieldMapController.h"
#import "CustomAnnotation.h"
#define HQ_latitude @"headquarters_latitude"
#define HQ_longitude @"headquarters_longitude"
#define HQ_coordinates @"headquarters_coordinates"
#import "PinSelectionViewController.h"

@interface FieldMapController ()

@end

@implementation FieldMapController 

@synthesize mapView;
@synthesize searchBar;
@synthesize geocoder = _geocoder;



- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

//ACCESS SAVED DATA FROM NSUSERDEFAULTS
-(void)viewWillAppear:(BOOL)animated{

    NSUserDefaults *uDefaults = [NSUserDefaults standardUserDefaults];
    if ([uDefaults boolForKey:@"headquarters_coordinates"])
    {

        CLLocationCoordinate2D savedCoordinate;
        savedCoordinate.latitude = [uDefaults doubleForKey:@"headquarters_latitude"];
        savedCoordinate.longitude = [uDefaults doubleForKey:@"headquarters_longitude"];

        NSLog(@"Your HQ is at coordinates %f and %f",savedCoordinate.latitude, savedCoordinate.longitude);

        CustomAnnotation *annHq =[[CustomAnnotation alloc] init];
        annHq.title=@"HQ";
        annHq.subtitle=@"";
        annHq.coordinate= savedCoordinate;
        [mapView addAnnotation:annHq];

        MKCoordinateRegion viewRegion = {{0.0, 0.0}, {0.0, 0.0}};
        viewRegion.center.latitude = savedCoordinate.latitude;
        viewRegion.center.longitude = savedCoordinate.longitude;
        viewRegion.span.longitudeDelta = 0.5f;
        viewRegion.span.latitudeDelta = 0.5f;
        [self.mapView setRegion:viewRegion animated:YES];
        [self.mapView setDelegate:self];


    }

}


- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    self.mapView.delegate = self;
    self.searchBar.delegate = self;


    //SEARCH BAR TOOLBAR WITH "DONE" AND "CANCEL" BUTTON
    UIToolbar* searchToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
    searchToolbar.barStyle = UIBarStyleBlackTranslucent;
    searchToolbar.items = [NSArray arrayWithObjects:
                           [[UIBarButtonItem alloc]initWithTitle:@"Cancel" style:UIBarButtonItemStyleBordered target:self action:@selector(cancelSearchBar)],
                           [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
                           nil];
    [searchToolbar sizeToFit];
    searchBar.inputAccessoryView = searchToolbar;


}

//WHEN PUSHING THE "CANCEL" BUTTON IN THE SEARCH BAR
-(void)cancelSearchBar
{
    [searchBar resignFirstResponder];
    searchBar.text = @"";

}

//PREPARE SEGUE FOR THE PIN SELECTOR VIEW
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([segue.identifier isEqualToString:@"ShowPinChoicesSegue"])
    {
        PinSelectionViewController *pinVC = [segue destinationViewController];

        CustomAnnotation *selectedAnnotation = (CustomAnnotation *)sender;
        pinVC.currentPinType = selectedAnnotation.pinType;
        pinVC.delegate = self;
    }
}

//WHAT HAPPENS WHEN THE "SEARCH" BUTTON AT THE SEARCH BAR KEYBOARD IS TAPPED
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar

{
    //Forward Geocoder
    if (!self.geocoder)
    {
        self.geocoder = [[CLGeocoder alloc] init];
    }

    NSString *address = [NSString stringWithFormat:@"%@", self.searchBar.text];

    [self.geocoder geocodeAddressString:address completionHandler:^(NSArray *placemarks, NSError *error) {
        if ([placemarks count] > 0)
        {
            CLPlacemark *placemark = [placemarks objectAtIndex:0];
            CLLocation *location = placemark.location;
            CLLocationCoordinate2D coordinate = location.coordinate;

            //Display Coordinates in Console
            NSLog (@"%f %f", coordinate.latitude, coordinate.longitude);

            MKCoordinateRegion region;
            MKCoordinateSpan span;
            span.latitudeDelta = 0.01;
            span.longitudeDelta = 0.01;
            region.span = span;
            region.center = coordinate;

            //Create Annotation with Callout Bubble that displays "No Information"
            MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
            [annotation setCoordinate:coordinate];
            [annotation setTitle:@"No Information"];
            [[self mapView] addAnnotation:annotation];
            [self.mapView setRegion:region animated:TRUE];
            [self.mapView regionThatFits:region];

            //Dismiss the Search Bar Keyboard
            [self.searchBar resignFirstResponder];

            //Delete text in Search Bar
            self.searchBar.text = @"";

        }
    }];

}

//CUSTOM ANNOTATION VIEW
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{

    if ([annotation isKindOfClass:[MKUserLocation class]])
    {
        return nil;
    }

    if ([annotation isKindOfClass:[CustomAnnotation class]])

    {

        MKPinAnnotationView *annotationView =
            (MKPinAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:((CustomAnnotation *)annotation).annotationViewImageName];
        if(annotationView == nil)
        {
            MKPinAnnotationView *customPinView =

            [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:((CustomAnnotation *)annotation).annotationViewImageName];

            if([[customPinView.annotation title] isEqualToString:@"HQ"])
            {

                //The pin for the HQ should be purple
                customPinView.pinColor = MKPinAnnotationColorPurple;

            }
            else 
            {
                //All other new pins should be "red" by default
                customPinView.image = [UIImage imageNamed:((CustomAnnotation *)annotation).annotationViewImageName];

            }

            customPinView.canShowCallout = YES;
            customPinView.animatesDrop = YES;

            //Right Callout Accessory Button
            UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
            customPinView.rightCalloutAccessoryView = rightButton;

            return customPinView;
        }
        else
        {
            annotationView.annotation = annotation;
        }
        return annotationView;
    }

    return nil;

}

//SHOW ACCESSORY VIEW WHEN BUTTON ON CALLOUT BUBBLE IS TAPPED
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
    if (![view.annotation isKindOfClass:[CustomAnnotation class]])
        return;
    CustomAnnotation *customAnnotation = (CustomAnnotation *)view.annotation;

    if (control.tag == 0)
    {
        [self performSegueWithIdentifier:@"ShowPinChoicesSegue" sender:customAnnotation];
    }
    else
    {
        [self onRightCalloutAccessoryViewTouched:control];

    }

}


-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{

    if(![view.annotation isKindOfClass:[CustomAnnotation class]])
        return;
    if (!view.rightCalloutAccessoryView)
    {
        UIButton *rightViewButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 48.0, 32.0)];
        [rightViewButton addTarget:self action:@selector(onRightCalloutAccessoryViewtouched:) forControlEvents:UIControlEventTouchUpInside];
        rightViewButton.tag = 1;
        view.rightCalloutAccessoryView = rightViewButton;
    }
}

-(void)onRightCalloutAccessoryViewTouched:(id)sender
{
    CustomAnnotation *selectedAnnotation = (CustomAnnotation *)[mapView.selectedAnnotations objectAtIndex:0];
    [self performSegueWithIdentifier:@"ShowPinChoicesSegue" sender:selectedAnnotation];
}


- (void)viewDidUnload
{
    self.mapView = nil;
    self.searchBar = nil;
}


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

//BUTTON TO SELECT NEW HQ
- (IBAction)selectHq:(UIBarButtonItem *)sender
{

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Select Headquarters"
                                                    message:@"Enter Address"
                                                   delegate:self
                                          cancelButtonTitle:@"Cancel"
                                          otherButtonTitles:@"Ok", nil];


    alert.alertViewStyle = UIAlertViewStylePlainTextInput;
    [[alert textFieldAtIndex:0] setKeyboardType:UIKeyboardTypeDefault];

    [alert show];

}

//REMOVING ALL PINS EXCEPT USER LOCATION
- (IBAction)resetPins:(UIBarButtonItem *)sender
{

    id userLocation = [mapView userLocation];
    NSMutableArray *pins = [[NSMutableArray alloc] initWithArray:[mapView annotations]];
    if ( userLocation != nil )
    {
        [pins removeObject:userLocation]; //avoid removing user location
    }

    [mapView removeAnnotations:pins];
    pins = nil;
    [[NSUserDefaults standardUserDefaults] removeObjectForKey:HQ_coordinates];
    [[NSUserDefaults standardUserDefaults] removeObjectForKey:HQ_longitude];
    [[NSUserDefaults standardUserDefaults] removeObjectForKey:HQ_latitude];
}

//ALERT VIEW TO ENTER ADDRESS OF HQ
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

{
    if (buttonIndex != alertView.cancelButtonIndex)

    {

        UITextField *field = [alertView textFieldAtIndex:0];
        field.placeholder = @"Enter HQ Address";

        if (!self.geocoder)
        {
            self.geocoder = [[CLGeocoder alloc] init];
        }

        NSString *hqAddress = [NSString stringWithFormat:@"%@", field.text];

        [self.geocoder geocodeAddressString:hqAddress completionHandler:^(NSArray *placemarks, NSError *error) {
            if ([placemarks count] > 0)
            {
                CLPlacemark *placemark = [placemarks objectAtIndex:0];
                CLLocation *location = placemark.location;
                CLLocationCoordinate2D hqCoordinate = location.coordinate;

                NSLog (@"Your new HQ is at coordinates %f and %f", hqCoordinate.latitude, hqCoordinate.longitude);

                MKCoordinateRegion region;
                MKCoordinateSpan span;
                span.latitudeDelta = 0.01;
                span.longitudeDelta = 0.01;
                region.span = span;
                region.center = hqCoordinate;

                MKPointAnnotation *hqAnnotation = [[MKPointAnnotation alloc] init];
                [hqAnnotation setCoordinate:hqCoordinate];
                [hqAnnotation setTitle:@"HQ"];

                [[self mapView] addAnnotation:hqAnnotation];
                [self.mapView setRegion:region animated:TRUE];
                [self.mapView regionThatFits:region];

                //Save to NSUserDefaults
                NSUserDefaults *uDefaults = [NSUserDefaults standardUserDefaults];
                [uDefaults setDouble:hqCoordinate.latitude forKey:HQ_latitude];
                [uDefaults setDouble:hqCoordinate.longitude forKey:HQ_longitude];
                [uDefaults setBool:YES forKey:HQ_coordinates];
                [uDefaults synchronize];

            }
        }];

    }

    else
    {
        //any actions for "Cancel"
    }

}

//DEFINES WHAT SELECTING THE NEW PIN COLOR DOES
-(void)userDidSelectPinType:(AnnotationPinType)aPinType
{
    CustomAnnotation *selectedAnnotation = (CustomAnnotation *)[mapView.selectedAnnotations objectAtIndex:0];
    selectedAnnotation.pinType = aPinType;
    [mapView removeAnnotation:selectedAnnotation];
    [mapView addAnnotation:selectedAnnotation];
    [self.navigationController dismissViewControllerAnimated:YES completion:nil];

}


@end

CustomAnnotation.m

#import "CustomAnnotation.h"
#import <CoreLocation/CoreLocation.h>

@implementation CustomAnnotation

@synthesize title, subtitle, coordinate;
@synthesize pinType;



-(id) initWithCoordinate:(CLLocationCoordinate2D)aCoordinate title:(NSString *)aTitle subtitle:(NSString *)aSubtitle

{

    if ((self = [super init]))
    {
        self.title = aTitle;
        self.coordinate = aCoordinate;
        self.subtitle = aSubtitle;
    }

    return self;

}

- (NSString *)annotationViewImageName
{
    switch (self.pinType)
    {
        case 0:
            return @"Red_Pin.png";
            break;
        case 1:
            return @"Green_Pin.png";
            break;
        case 2:
            return @"Purple_Pin.png";
            break;
        default:
            break;
    }
}

- (NSString *)title
{
    return title;
}

- (NSString *)subtitle
{
    return subtitle;
}

@end

PinSelectionViewController.m

#import "PinSelectionViewController.h"

@interface PinSelectionViewController ()

@end

@implementation PinSelectionViewController
@synthesize delegate;
@synthesize currentPinType;

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

- (void)tableView:(UITableView *) tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(indexPath.row ==currentPinType)
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
}


#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    [self.delegate userDidSelectPinType:indexPath.row];

}

@end

PinSelectionDelegateProtocol.h

#import <Foundation/Foundation.h>

typedef enum
{
    RED_PIN,
    GREEN_PIN,
    PURPLE_PIN
} AnnotationPinType;

@protocol PinSelectionDelegate <NSObject>

@required

-(void)userDidSelectPinType:(AnnotationPinType)aPinType;

@end

1 个答案:

答案 0 :(得分:0)

我看到的问题是您viewForAnnotation方法的早期问题。您正确地重用了注释视图,但错误地认为已正确配置重用视图。当您检查视图是否为零时,您只需配置全新视图以使其颜色与注释的名称相匹配。您需要做的是检查它是否为零,如果是,则创建一个新的并关闭if。然后确保新的和重用的注释视图的引脚颜色,标题,附件视图等设置为您想要的用于该注释

此外,您无法设置.image的{​​{1}},它只会被覆盖。如果您真的想要设置自定义图像,则必须使用常规MKAnnotationView。如果您可以使用标准的红色,绿色和蓝色引脚,那么只需将MKPinAnnotationView设置为您想要的任何内容。