0

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

我偶然发现了一个教程,该教程允许用户选择注释引脚并通过显示模态视图来更改其引脚颜色。我仔细按照教程进行操作,但由于某种原因,它无法正常工作。The modal view with the pin selection is displayed, but when a pin color is selected, the pin color on the map view is not updated. 此外,我不想使用“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

自定义注释.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
4

1 回答 1

0

我看到的问题是您viewForAnnotation方法的早期阶段。您正确地重用了注释视图,但错误地假设重用的视图配置正确。当您检查视图是否为零时,您只需将全新的视图配置为具有与注释名称匹配的引脚颜色。你需要做的是检查它是否为 nil,如果是则创建一个新的并关闭它if。然后确保新的和重用的注释视图都按照你想要的注释设置了它们的引脚颜色、标题、附件视图等。

你也不能设置.imagea MKPinAnnotationView,它只会被覆盖。如果你真的想设置自定义图像,你必须使用常规的 MKAnnotationView。如果您可以使用标准的红色、绿色和蓝色引脚,那么只需将其设置.pinColor为您想要的任何值。

于 2013-09-10T08:18:32.880 回答