Save certain pin annotations with NSArray
Here is Question 2 of 3:
My app is a map view were the user can enter an address which will put a
purple pin on the map for the HQ. Secondly, the user can enter any
address, which will put as many red pins on the map as required. While I
am able to save the coordinates of one pin with NSUserDefaults, such as
the HQ pin in my code below, how can I change multiple of my red pins?
Someone suggested to use NSArray to do this, but I am too inexperienced
with this. Any help?
Here is my code:
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
No comments:
Post a Comment