My app is a map view where 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 a red pin on the map. I would like to be able to change the pin color of the red pins to either red, green, or purple.
I stumbled across a tutorial that will allow the user to select an annotation pin and change its pin color by displaying a modal view. I followed the tutorial meticulously, but for some reason, it is not working correctly. 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. Additionally, instead of using "png" images to display custom pins, I would like to use the built-in standard pins (since that's all I need). How can I adjust my code below to achieve this? I added my entire 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
The problem I see is early on in your viewForAnnotation method. You correctly reuse annotationviews but incorrectly assume that the reused view is configured properly. When you check if the view is nil you only configure brand new ones to have the pin colour that matches the annotation's name. What you need to do is check if it is nil, if is then make a new one and close that if. Then make sure both new and reused annotationviews have their pin colour, title, accessory view etc set up as you want it for that annotation.
Also you can't set the .image of an MKPinAnnotationView, it'll just get overwritten. If you really want to set a custom image you have to use a regular MKAnnotationView. If you are ok with using the standard red, green and blue pins then just set the .pinColor to whatever you want.
Related
I am stuck with a problem on the mapView. I am really sorry to ask this question but I have searched for almost one day to look into this issue but I don't find a solution to fix it.
#interface MapViewController ()<CLLocationManagerDelegate, MKMapViewDelegate, UITextFieldDelegate, CheckInDelegate, NotificationsViewControllerDelegate, ReportVCDelegate, TutorialViewControllerDelegate> {
CLLocationManager *locationManager;
NSTimer *refreshTimer;
int rangeValue;
CheckInViewController *checkInVC;
TutorialViewController *tutorialVC1;
TutorialViewController *tutorialVC2;
UIImageView *imgAvatar;
NSArray *markers;
}
#property (weak, nonatomic) IBOutlet UIView *viewSearch;
#property (weak, nonatomic) IBOutlet RateView *viewRate;
#property (weak, nonatomic) IBOutlet UIView *viewBottom;
#property (weak, nonatomic) IBOutlet UILabel *lblUsername;
#property (weak, nonatomic) IBOutlet UITextField *txtSearch;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *btnNotifications;
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomSpace;
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomHeight;
#property (weak, nonatomic) IBOutlet UIButton *btnBottom;
#property (weak, nonatomic) IBOutlet HandsawayMapView *mapView;
#property (weak, nonatomic) IBOutlet UIView *mapViewContainer;
#property (strong, nonatomic) MKPlacemark *searchMarker;
#property (strong, nonatomic) MKUserLocation *myMarker;
#property (weak, nonatomic) MapToolbarViewController *mapToolbar;
#property (strong, atomic) NSArray *allMapMarkers;
#property (strong, nonatomic) NSNumber *aggressionIdToCenter;
#end
#implementation MapViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// [[UserModel sharedModel] setUserHome:#(1)];
rangeValue = 300;
self.viewSearch.layer.masksToBounds = NO;
self.viewSearch.layer.shadowRadius = 0.5f;
self.viewSearch.layer.shadowColor = [UIColor blackColor].CGColor;
self.viewSearch.layer.shadowOffset = CGSizeMake(0.0f, 0.5f);
self.viewSearch.layer.shadowOpacity = 0.5f;
self.viewRate.starCount = 4;
self.viewRate.step = 1.0f;
self.viewRate.starNormalColor = UIColorFromRGB(0xD8D8D8);
self.viewRate.starFillColor = UIColorFromRGB(0xFF5B59);
self.viewRate.rating = 3.0f;
self.viewRate.starSize = 20.0f;
self.viewRate.padding = 8.0f;
locationManager = [[CLLocationManager alloc] init];
[locationManager requestWhenInUseAuthorization];
locationManager.delegate = self;
[DbHelper saveActivationWithNumer:#(1)];
imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
}];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSNumber *agressionID = [[NSUserDefaults standardUserDefaults] valueForKey:#"aggression_id"];
if (agressionID && agressionID != 0)
{
self.aggressionIdToCenter = agressionID;
[[NSUserDefaults standardUserDefaults] setValue:0 forKey:#"aggression_id"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if (self.aggressionIdToCenter != nil) {
[self centerOnAggressionWithId:self.aggressionIdToCenter];
self.aggressionIdToCenter = nil;
}
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[locationManager stopUpdatingLocation];
didSetLocation = NO;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UIView*)locationPin {
User *user = [DbHelper getCurrentUser];
UIImage *pin = [UIImage imageNamed:#"marker-person"];
if([user.isCurrent boolValue]) {
pin = [UIImage imageNamed:#"my-pin"];
}
UIImageView *pinImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 39, 48)];
[pinImageView setImage:pin];
UIView *markerContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 39, 48)];
[markerContainer addSubview:pinImageView];
imgAvatar = [[UIImageView alloc] initWithFrame:CGRectMake(4.5, 4.5, 30, 30)];
[imgAvatar setContentMode:UIViewContentModeScaleAspectFill];
imgAvatar.layer.cornerRadius = 15;
imgAvatar.clipsToBounds = YES;
[markerContainer addSubview:imgAvatar];
if([user.isPictureHidden boolValue]) {
[imgAvatar setImage:[user avatarPlaceholder]];
}
else {
[imgAvatar setImageWithURL:[NSURL URLWithString:user.pictureURL] placeholderImage:[user avatarPlaceholder]];
}
[pinImageView setBackgroundColor:[UIColor clearColor]];
[imgAvatar setBackgroundColor:[UIColor clearColor]];
[markerContainer setBackgroundColor:[UIColor clearColor]];
return markerContainer;
}
- (void)ckeckUserImage
{
User *user = [DbHelper getCurrentUser];
if([user.isPictureHidden boolValue]) {
[imgAvatar setImage:[user avatarPlaceholder]];
}
else {
[imgAvatar setImageWithURL:[NSURL URLWithString:user.pictureURL] placeholderImage:[user avatarPlaceholder]];
}
if (self.mapToolbar.currentUser)
{
[self.mapToolbar setCurrentUser];
}
}
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if([segue.identifier isEqualToString:#"PresentInfo"]) {
self.mapToolbar = segue.destinationViewController;
self.mapToolbar.height = self.bottomHeight;
self.mapToolbar.masterVC = self;
} else if ([segue.identifier isEqualToString:#"NotificationsSegue"] && [segue.destinationViewController isKindOfClass:[NotificationsViewController class]]) {
NotificationsViewController *destination = (NotificationsViewController *)segue.destinationViewController;
destination.delegate = self;
}
else if([segue.identifier isEqualToString:#"ActionSheetMap"]) {
self.VCactionSheetMap = segue.destinationViewController;
self.VCactionSheetMap.delegate = self.mapToolbar;
} else if ([segue.identifier isEqualToString:#"mapToReport"]) {
self.reportVC = (ReportVC *)segue.destinationViewController;
self.reportVC.delegate = self;
}
}
- (IBAction)onMenu:(id)sender {
[self.frostedViewController presentMenuViewController];
}
-(IBAction)onLocate:(id)sender {
self.txtSearch.text = #"";
[self.mapView removeAnnotation:self.searchMarker];
self.searchMarker = nil;
didSetLocation = NO;
}
- (IBAction)onCheckIn:(id)sender {
if([[NSUserDefaults standardUserDefaults] valueForKey:#"tutorials2"]) {
self.btnCheckin.hidden = YES;
checkInVC = [self.storyboard instantiateViewControllerWithIdentifier:#"NewCheckin"];
checkInVC.delegate = self;
checkInVC.model = [[CheckInModel alloc] init];
if(_searchMarker != nil) {
checkInVC.model.longitude = (double) _searchMarker.coordinate.longitude;
checkInVC.model.latitude = (double) _searchMarker.coordinate.latitude;
}
else {
checkInVC.model.longitude = (double) locationManager.location.coordinate.longitude;
checkInVC.model.latitude = (double) locationManager.location.coordinate.latitude;
}
if([sender isKindOfClass:[NSNumber class]]) {
checkInVC.agressionId = sender;
}
UIWindow *currentWindow = [UIApplication sharedApplication].keyWindow;
[currentWindow addSubview:checkInVC.view];
}
else {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if(![[NSUserDefaults standardUserDefaults] valueForKey:#"tutorials2"]) {
[self.navigationController setNavigationBarHidden:YES animated:YES];
[self.btnCheckin setAdjustsImageWhenHighlighted:NO];
[self.btnCheckin setUserInteractionEnabled:NO];
UIStoryboard *tutorials = [UIStoryboard storyboardWithName:#"Tutorial" bundle:nil];
tutorialVC2 = (TutorialViewController *)[tutorials instantiateViewControllerWithIdentifier:[NSString stringWithFormat:#"Tutorial%ld", (long)2]];
tutorialVC2.delegate = self;
[[tutorialVC2 view] setFrame:self.view.bounds];
[self.view insertSubview:[tutorialVC2 view] belowSubview:self.btnCheckin];
[[NSUserDefaults standardUserDefaults] setValue:#YES forKey:#"tutorials2"];
}
});
}
}
- (IBAction)onNotifications:(id)sender {
if([[NSUserDefaults standardUserDefaults] valueForKey:#"tutorials1"]) {
[self performSegueWithIdentifier:#"NotificationsSegue" sender:nil];
}
else {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if(![[NSUserDefaults standardUserDefaults] valueForKey:#"tutorials1"]) {
[self.navigationController setNavigationBarHidden:YES animated:YES];
UIStoryboard *tutorials = [UIStoryboard storyboardWithName:#"Tutorial" bundle:nil];
tutorialVC1 = (TutorialViewController *)[tutorials instantiateViewControllerWithIdentifier:[NSString stringWithFormat:#"Tutorial%ld", (long)1]];
tutorialVC1.delegate = self;
[[tutorialVC1 view] setFrame:self.view.bounds];
[self.view addSubview:[tutorialVC1 view]];
[[NSUserDefaults standardUserDefaults] setValue:#YES forKey:#"tutorials1"];
}
});
});
}
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
[manager startUpdatingLocation];
}
BOOL didSetLocation;
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray<CLLocation *> *)locations {
if(locations.count > 0 ) {
CLLocation *aUserLocation = locations[0];
self.myMarker.coordinate = aUserLocation.coordinate;
// if(_myMarker == nil) {
// GMSMarker *marker = [[GMSMarker alloc] init];
// marker.iconView = [[DbHelper getCurrentUser] locationPin];
// marker.map = mapView_;
// _myMarker = marker;
// }
// _myMarker.position = aUserLocation.coordinate;
if(!didSetLocation) {
didSetLocation = YES;
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.01557113906538632;
span.longitudeDelta = 0.02284631241712987;
CLLocationCoordinate2D location;
location.latitude = aUserLocation.coordinate.latitude;
location.longitude = aUserLocation.coordinate.longitude;
region.span = span;
region.center = location;
[self.mapView setRegion:region animated:YES];
// [APICLIENT locateUserWithCoordinates:location
// completion:^(NSDictionary *result) {
//
// } error:^{
//
// }];
}
}
}
#pragma mark - Bottom bar
BOOL isBottomBarShown = YES;
}
#pragma mark - MKMapViewDelegate
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
// NSLog(#"longitured : %#, lattitude: %#", #(mapView.region.span.longitudeDelta), #(mapView.region.span.latitudeDelta));
[self hideBottomView];
[refreshTimer invalidate];
refreshTimer = [NSTimer scheduledTimerWithTimeInterval:0.8
target:self
selector:#selector(refreshMapMarkersWithCoordinates:)
userInfo:#{#"longitude" : #(mapView.region.center.longitude), #"latitude" : #(mapView.region.center.latitude), #"range" : #(rangeValue)}
repeats:NO];
}
- (nullable MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
if(![annotation isKindOfClass:[MKPlacemark class]]) {
MKAnnotationView * annotationView = [MKAnnotationView new];
if([annotation isKindOfClass:[MKUserLocation class]]) {
UIView *userView = [self locationPin];
[annotationView setFrame:userView.frame];
[annotationView addSubview:userView];
self.myMarker = annotation;
[self.mapView sendSubviewToBack:annotationView];
}
else {
annotationView.annotation = annotation;
Marker *dbmarker = ((MarkerAnnotation*)annotation).userData;
if(dbmarker.agression != nil) {
[annotationView setImage:[dbmarker markerImage]];
[self.mapView bringSubviewToFront:annotationView];
}
else if(dbmarker.user != nil) {
UIView *userView = [dbmarker userMarkerView];
[annotationView setFrame:userView.frame];
[annotationView addSubview:userView];
[self.mapView bringSubviewToFront:annotationView];
}
}
return annotationView;
}
return nil;
}
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
if(view.annotation != self.searchMarker && view.annotation != self.myMarker) {
if([view.annotation isKindOfClass:[MKUserLocation class]]) {
}
else {
[self selectMarker:((MarkerAnnotation*)view.annotation).userData];
}
}
else
{
if (view.annotation == self.myMarker)
{
[self.mapToolbar setCurrentUser];
}
[self showBottomView];
}
}
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view {
if(view.annotation != self.searchMarker && view.annotation != self.myMarker) {
if([view.annotation isKindOfClass:[MKUserLocation class]]) {
}
else {
[self hideBottomView];
}
}
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
[APICLIENT locateUserWithCoordinates:userLocation.location.coordinate
completion:^(NSDictionary *result) {
} error:^{
}];
}
#pragma mark - GMSMap delegate
//- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
// [self selectMarker:marker];
// return YES;
//}
- (void)selectMarker:(Marker *)marker {
Marker *dbMarker = marker;
if(dbMarker.agression != nil) {
[APICLIENT getAgressionWithId:dbMarker.agression.webID
completion:^(Marker *newmarker) {
[APICLIENT getUserById:[newmarker.user.webID stringValue]
completion:^(User *result) {
self.mapToolbar.marker = newmarker;
//[self showBottomView];
} error:^{
}];
} error:^{
}];
}
else {
[APICLIENT getUserById:[dbMarker.user.webID stringValue]
completion:^(User *result) {
self.mapToolbar.marker = dbMarker;
[self showBottomView];
} error:^{
}];
}
}
-(void)reloadMarkers {
[APICLIENT getMapMarkersAroundMeWithCoordinates:self.mapView.region.center
range:#(rangeValue)
completion:^(NSArray *result) {
[self updateDistance];
NSArray *oldAnnotations = [self.mapView.annotations filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF.class == %#", [MarkerAnnotation class]]];
oldAnnotations = [oldAnnotations valueForKey:#"userData"];
markers = [Marker MR_findAllWithPredicate:[NSPredicate predicateWithFormat:#"NOT (SELF IN %#)", oldAnnotations]];
//[self.mapView removeAnnotations:self.mapView.annotations];
NSMutableArray *allMapMarkersMutable = [[NSMutableArray alloc] init];
for(Marker *dbmarker in markers) {
MarkerAnnotation *marker = [[MarkerAnnotation alloc] init];
marker.coordinate = CLLocationCoordinate2DMake([dbmarker.latitude doubleValue], [dbmarker.longitude doubleValue]);
marker.userData = dbmarker;
[self.mapView addAnnotation:marker];
[allMapMarkersMutable addObject:marker];
}
self.allMapMarkers = [[allMapMarkersMutable copy] arrayByAddingObjectsFromArray:oldAnnotations];
if(_searchMarker != nil && ![self.mapView.annotations containsObject:_searchMarker]) {
[self.mapView addAnnotation:_searchMarker];
}
if(self.aggressionIdToCenter != nil) {
[self centerOnAggressionWithId:self.aggressionIdToCenter];
self.aggressionIdToCenter = nil;
}
} error:^{
}];
/*NSArray *oldAnnotations = [self.mapView.annotations filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF.class == %#", [MarkerAnnotation class]]];
oldAnnotations = [oldAnnotations valueForKey:#"userData"];
markers = [Marker MR_findAllWithPredicate:[NSPredicate predicateWithFormat:#"NOT (SELF IN %#)", oldAnnotations]];
// [self.mapView removeAnnotations:self.mapView.annotations];
NSMutableArray *allMapMarkersMutable = [[NSMutableArray alloc] init];
for(Marker *dbmarker in markers) {
MarkerAnnotation *marker = [[MarkerAnnotation alloc] init];
marker.coordinate = CLLocationCoordinate2DMake([dbmarker.latitude doubleValue], [dbmarker.longitude doubleValue]);
marker.userData = dbmarker;
[self.mapView addAnnotation:marker];
[allMapMarkersMutable addObject:marker];
}
self.allMapMarkers = [[allMapMarkersMutable copy] arrayByAddingObjectsFromArray:oldAnnotations];
if(_searchMarker != nil && ![self.mapView.annotations containsObject:_searchMarker]) {
[self.mapView addAnnotation:_searchMarker];
}
if(self.aggressionIdToCenter != nil) {
[self centerOnAggressionWithId:self.aggressionIdToCenter];
self.aggressionIdToCenter = nil;
}*/
}
//-(void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate {
// [self hideBottomView];
//}
#pragma mark - UITextFieldDelegate and place search
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[self.view endEditing:YES];
MKCoordinateRegion newRegion;
newRegion.center.latitude = locationManager.location.coordinate.latitude;
newRegion.center.longitude = locationManager.location.coordinate.longitude;
// Setup the area spanned by the map region:
// We use the delta values to indicate the desired zoom level of the map,
// (smaller delta values corresponding to a higher zoom level).
// The numbers used here correspond to a roughly 8 mi
// diameter area.
//
newRegion.span.latitudeDelta = 0.112872;
newRegion.span.longitudeDelta = 0.109863;
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = textField.text;
request.region = newRegion;
MKLocalSearch *localSearch = [[MKLocalSearch alloc] initWithRequest:request];
MKLocalSearchCompletionHandler completionHandler = ^(MKLocalSearchResponse *response, NSError *error) {
if (error != nil) {
// NSString *errorStr = [[error userInfo] valueForKey:NSLocalizedDescriptionKey];
// UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Could not find places"
// message:errorStr
// delegate:nil
// cancelButtonTitle:#"OK"
// otherButtonTitles:nil];
// [alert show];
} else {
NSArray<MKMapItem *> *mapItems = [response mapItems];
if(mapItems.count > 0) {
MKCoordinateRegion boundingRegion = response.boundingRegion;
MKMapItem *item = mapItems[0];
self.searchMarker = item.placemark;
[self.mapView addAnnotation:item.placemark];
[self.mapView setRegion:boundingRegion animated:YES];
}
}
};
[localSearch startWithCompletionHandler:completionHandler];
double radians(double degrees) {
return degrees * M_PI / 180.0;
}
double degrees(double radians) {
return radians * 180.0 / M_PI;
}
const CLLocationDegrees kLatLonEarthRadius = 6371.0;
CLLocationCoordinate2D LatLonDestPoint(CLLocationCoordinate2D origin, double bearing, CLLocationDistance distance) {
double brng = radians(bearing);
double lat1 = radians(origin.latitude);
double lon1 = radians(origin.longitude);
CLLocationDegrees lat2 = asin(sin(lat1) * cos(distance / kLatLonEarthRadius) +
cos(lat1) * sin(distance / kLatLonEarthRadius) * cos(brng));
CLLocationDegrees lon2 = lon1 + atan2(sin(brng) * sinf(distance / kLatLonEarthRadius) * cos(lat1),
cosf(distance / kLatLonEarthRadius) - sin(lat1) * sin(lat2));
lon2 = fmod(lon2 + M_PI, 2.0 * M_PI) - M_PI;
CLLocationCoordinate2D coordinate;
if (! (isnan(lat2) || isnan(lon2))) {
coordinate.latitude = degrees(lat2);
coordinate.longitude = degrees(lon2);
}
return coordinate;
}
#pragma mark - CheckInDelegate
- (void)willRemoveCheckinView {
[[UIApplication sharedApplication] setStatusBarHidden:NO
withAnimation:UIStatusBarAnimationSlide];
[self.navigationController setNavigationBarHidden:NO
animated:YES];
}
The problem is you are adding marker in MKLocalSearchCompletionHandler, so remove below line from MKLocalSearchCompletionHandler will solved your issue.
[self.mapView addAnnotation:item.placemark];
You can remove all annotation pins from MKMapView by using following code
for (int i =0; i < [_mapView.annotations count]; i++) {
if ([[_mapView.annotations objectAtIndex:i] isKindOfClass:[YOURANNOTATIONCLASS class]]) {
[_mapView removeAnnotation:[_mapView.annotations objectAtIndex:i]];
}
}
If you want to remove Annotation while search then remove bellow code in textFieldShouldReturn method.
Find method:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
}
Then Comment or Remove bellow code
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = textField.text;
request.region = newRegion;
MKLocalSearch *localSearch = [[MKLocalSearch alloc] initWithRequest:request];
MKLocalSearchCompletionHandler completionHandler = ^(MKLocalSearchResponse *response, NSError *error) {
if (error != nil) {
// NSString *errorStr = [[error userInfo] valueForKey:NSLocalizedDescriptionKey];
// UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Could not find places"
// message:errorStr
// delegate:nil
// cancelButtonTitle:#"OK"
// otherButtonTitles:nil];
// [alert show];
} else {
NSArray<MKMapItem *> *mapItems = [response mapItems];
if(mapItems.count > 0) {
MKCoordinateRegion boundingRegion = response.boundingRegion;
MKMapItem *item = mapItems[0];
self.searchMarker = item.placemark;
[self.mapView addAnnotation:item.placemark];
[self.mapView setRegion:boundingRegion animated:YES];
}
}
};
Hope it will help you
I'm using Parse.com as a backend and i want to show Geopoints on my map.
Every Geopoint is also connected with a database boolean field true or false.
How can I show a green pins colour for the "true" gepoint and red pins for the "false" Geopoint?
Here is code for the MapViewController.m
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
I have a function to perform the query against the parse.com database to return me all location data. It is called within the viewDidLoad Method.
- (void)viewDidLoad
{
[super viewDidLoad];
[self getAllStations];
}
Then I set the annotationView like this:
#pragma mark - MapViewDelegate
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)geoPointAnnotation {
static NSString *MapViewAnnotationIdentifier = #"Places";
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:MapViewAnnotationIdentifier];
if (geoPointAnnotation == mapView.userLocation) {
return nil;
} else {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:geoPointAnnotation reuseIdentifier:MapViewAnnotationIdentifier];
annotationView.pinColor = MKPinAnnotationColorGreen;
annotationView.canShowCallout = YES;
annotationView.draggable = YES;
annotationView.animatesDrop = YES;
}
return annotationView;
}
Here is the Code for the MapViewAnnotation.m (Object):
#import "MapViewAnnotation.h"
#import "Parse/Parse.h"
#interface MapViewAnnotation ()
#property (nonatomic, strong) PFObject *object;
#end
#implementation MapViewAnnotation
#pragma mark - Initialization
- (id)initWithObject:(PFObject *)aObject {
self = [super init];
if (self) {
_object = aObject;
PFGeoPoint *geoPoint = self.object[#"location"];
[self setGeoPoint:geoPoint]; }
return self;
}
- (void)setGeoPoint:(PFGeoPoint *)geoPoint {
_coordinate = CLLocationCoordinate2DMake(geoPoint.latitude, geoPoint.longitude);
NSString *streetName = self.object[#"adress"];
_title = [NSString stringWithFormat:#"%#", [_object objectForKey:#"name"]];
[PFGeoPoint geoPointForCurrentLocationInBackground:^(PFGeoPoint *currentLocationGeoPoint, NSError *error) { //Get current Location
if (!error) {
PFGeoPoint *distanceGeoPoint = [_object objectForKey:#"location"];
double distanceDouble = [currentLocationGeoPoint distanceInKilometersTo:distanceGeoPoint];
//NSLog(#"Distance: %.1f",distanceDouble);
_subtitle = [NSString stringWithFormat:#"%# - Distance: %.1f km", streetName, distanceDouble];
}
}];
}
#end
Can anyone give me a hint how I can show green and red pins based on a boolean?
Thanks in advance!
You can customize the pin annotation view,
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
{
return nil;
}
MKAnnotationView *flagAnnotationView =
[self.mapView dequeueReusableAnnotationViewWithIdentifier:SFAnnotationIdentifier];
if (flagAnnotationView == nil)
{
MKPinAnnotationView *customPinView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:SFAnnotationIdentifier];
if(annotation.coordinate.latitude==42.0000 && annotation.coordinate.longitude==-87.65000)
//you have to keep the latitude and longitude of the pins to which you can set the colour of the pin according to that latlong
customPinView.pinColor = MKPinAnnotationColorGreen;
else
customPinView.pinColor = MKPinAnnotationColorRed;
customPinView.animatesDrop = YES;
customPinView.canShowCallout = YES;
return customPinView;
}
else
{
flagAnnotationView.annotation = annotation;
}
return flagAnnotationView;
return nil;
}
in your annotation.h file declare a nsstring as below
#property (strong , nonatomic)NSString *pinColour;
and in the implemention file do the below to check for the colour
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation{
//other code above
if ([[annotation pinColour] isEqualToString:#"Red"]) {
annotationView.pinColor = MKPinAnnotationColorRed;
}else{
annotationView.pinColor = MKPinAnnotationColorGreen;
}
}
and inside the for loop of parse, tag the relevant with to pass wither colour
annotation.pinColour = #"Red";
Can anyone give me a hint how I can show green and red pins based on a boolean?
BOOL colorRed = YES;
if (colorRed) annotationView.pinColor = MKPinAnnotationColorRed;
else annotationView.pinColor = MKPinAnnotationColorGreen;
Is that what you mean?
I have this code:
// MapViewController.h
#import <Foundation/Foundation.h>
#import "MyCLController.h"
#import <MapKit/MapKit.h>
#class ShowsContainerController;
#interface MapViewController : UIViewController <MyCLControllerDelegate,MKMapViewDelegate> {
MyCLController *locationController;
MKMapView *mapView;
}
- (void)locationUpdate:(CLLocation *)location;
- (void)locationError:(NSError *)error;
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
#property (assign) BOOL updateMap;
#property (strong) ShowsContainerController *parent;
#end
// MapViewController.m
#import "MapViewController.h"
#import "ShowsContainerController.h"
#define METERS_PER_MILE 1609.344
#implementation MapViewController
#synthesize parent, mapView;
- (void)viewDidLoad
{
[super viewDidLoad];
self.updateMap = YES;
locationController = [[MyCLController alloc] init];
locationController.delegate = self;
[locationController.locationManager startUpdatingLocation];
mapView.delegate = self;
}
- (void)locationUpdate:(CLLocation *)location {
if( self.updateMap ){
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, 0.5*METERS_PER_MILE, 0.5*METERS_PER_MILE);
[mapView setRegion:viewRegion animated:YES];
self.parent = (ShowsContainerController *)self.parentViewController;
[self.parent setLocation:location];
self.updateMap = NO;
}
}
- (void)locationError:(NSError *)error {
NSLog([error localizedDescription]);
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.parent.mapReady = YES;
if( self.parent.locationSet ){
[self.parent callApi];
}
}
#pragma mark MKMapViewDelegate
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
NSLog(#"delegating user location");
// if it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
NSLog(#"delegating pins");
static NSString* ShowAnnotationIdentifier = #"showAnnotationIdentifier";
MKPinAnnotationView* pinView = (MKPinAnnotationView *)
[mapView dequeueReusableAnnotationViewWithIdentifier:ShowAnnotationIdentifier];
if (!pinView)
{
// if an existing pin view was not available, create one
MKPinAnnotationView* customPinView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:ShowAnnotationIdentifier];
customPinView.enabled = YES;
customPinView.pinColor = MKPinAnnotationColorRed;
customPinView.animatesDrop = YES;
customPinView.canShowCallout = YES;
return customPinView;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
#pragma mark -
#end
And here's the code adding my pins; it isn't fired until an api call is made, which is after viewDidAppear is fired:
- (void)placeAnnotations:(NSArray *)shows
{
NSEnumerator *e = [shows objectEnumerator];
id show;
NSMutableArray *annotations = [[NSMutableArray alloc] init];
while (show = [e nextObject]) {
double lat = [[[[[show objectForKey:#"venue"] objectForKey:#"location"] objectForKey:#"geo:point"] objectForKey:#"geo:lat"] doubleValue];
double lng = [[[[[show objectForKey:#"venue"] objectForKey:#"location"] objectForKey:#"geo:point"] objectForKey:#"geo:long"] doubleValue];
ShowAnnotation *annotation = [[ShowAnnotation alloc]
initWithCoordinate:CLLocationCoordinate2DMake(lat, lng)
withMap:self.mapController.mapView
withTitle:[show objectForKey:#"title"]
withSubtitle:[[show objectForKey:#"venue"] objectForKey:#"name" ]];
[annotations addObject:annotation];
}
NSLog(#"adding annotations");
[self.mapController.mapView addAnnotations:annotations];
}
The log shows "delegating user location", but never "delegating pins". It doesn't even fire viewForAnnotation more than the one initial time for the user's location.
The delegation seems to be working, otherwise I wouldn't be able to capture this selector, but why is it firing for only the user location and not firing for subsequent annotation additions?
I'm trying to display mapview with an array of coordinates. So, i load the latitudes and longitudes from array where those are contains. It is showing perfectly. Now, i want to display one paritcular latitude & longitude with different color pin. I've referred this answer no such different i can't see.
ViewController.m
-(void)showMap:
{
...
...
DataProvider *d = [DataProvider getInstance];
NSInteger numb = sender.view.tag;
d.colorlatitude = [[arraxy objectAtIndex:numb] objectForKey:#"lat"];
d.colorlongitude = [[arraxy objectAtIndex:numb] objectForKey:#"lng"];
[d._address removeAllObjects];
[arraxy removeObjectAtIndex:sender.view.tag];
d._address = arraxy;
MapViewController *map = [[MapViewController alloc]initWithNibName:#"MapViewController" bundle:nil];
[self.navigationController pushViewController:map animated:YES];
}
MapViewController.m
-(void)viewWillAppear:(BOOL)animated
{
DataProvider *d = [DataProvider getInstance];
[_mapView removeAnnotations:_mapView.annotations];
RegisterViewController *appDelegate = [[RegisterViewController alloc]init];
[_mapView setShowsUserLocation:YES];
[_mapView setRegion:MKCoordinateRegionMakeWithDistance([appDelegate.locationManager location].coordinate, 1000, 1000)];
[_mapView setUserTrackingMode:MKUserTrackingModeNone];
MKCoordinateRegion rregion = {{0.0,0.0},{0.0,0.0}};
rregion.center.latitude = [d.colorlatitude floatValue];
rregion.center.longitude = [d.colorlongitude floatValue];
rregion.span.latitudeDelta=0.001f;
rregion.span.longitudeDelta=0.001f;
[_mapView setRegion:rregion];
MapviewAnnotations *add = [[MapviewAnnotations alloc]init];
add.coordinate = rregion.center;
[_mapView addAnnotation:add];
if (d._address)
{
for (int i=0; i<[d._address count]; i++)
{
NSDictionary *dic=[d._address objectAtIndex:i];
MKCoordinateRegion region={{0.0,0.0},{0.0,0.0}};
region.center.latitude=[[dic objectForKey:#"lat"]floatValue];
region.center.longitude=[[dic objectForKey:#"lng"]floatValue];
region.span.latitudeDelta=0.001f;
region.span.longitudeDelta=0.001f;
[_mapView setRegion:region];
MapviewAnnotations *ann=[[MapviewAnnotations alloc]init];
ann.coordinate=region.center;
[_mapView addAnnotation:ann];
}
}
[super viewWillAppear:YES];
}
and my MKMapView's delegate method is
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if (![annotation isKindOfClass:[MapviewAnnotations class]])
{
return nil;
}
static NSString *reuseId = #"currentloc";
MKPinAnnotationView *annView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseId];
if (annView == nil)
{
annView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId];
annView.animatesDrop = NO;
annView.canShowCallout = YES;
annView.calloutOffset = CGPointMake(-5, 5);
}
else
{
annView.annotation = annotation;
}
DataProvider *mvAnn = [DataProvider getInstance];
if (mvAnn.colorlatitude) // here i'm checking the condition.
{
annView.pinColor = MKPinAnnotationColorGreen;
}
else
{
annView.pinColor = MKPinAnnotationColorRed;
}
return annView;
}
I'm just writting the condition if the co-ordinate is there i've to plot the green color pin to that particular coordinate only. How to achieve this?
The difference between your code and the one Hinata has referred you to is that the if statement in the other code uses a value (yesno) on the annotation it is currently drawing to decide what colour to use. You are getting a value from DataProvider but not telling it which annotation you are drawing, so the instance it gives you is just what ever the instance method feels like returning at the time the map is asking for the pin. You need to tell it what you're drawing for it to decide what to put into colorlatitude
I've done this through some flags like below inside of my - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
MapviewAnnotations *mvAnn = (MapviewAnnotations *)annotation;
if (mvAnn.flag == 1)
{
annView.pinColor = MKPinAnnotationColorGreen;
}
else if (mvAnn.flag == 10)
{
annView.pinColor = MKPinAnnotationColorPurple;
}
else
{
annView.pinColor = MKPinAnnotationColorRed;
}
In my viewWillAppear i received the coordinates from DataProvider and assigned with separate MapviewAnnotations with flags and differentiate it with three type of pins simply.
Cheers!
I have a MapView, the annotations comes from a property list.
Now I would like to see more data in the detail view.
Unfortunately I do not how to program the Segue, so that data can be displayed.
I hope you understand what I mean. My english is not so good ...
I know that there is missing some in the method prepareforSegue.
I am using storyboard.
In advance thank you for your help ...
regards
#import "MapViewNewController.h"
#import "MapViewAnnotation.h"
#import "SetCardController.h"
#interface MapViewNewController ()
#end
#implementation MapViewNewController
#synthesize recipesDictionary = _recipesDictionary;
#synthesize mapView;
#synthesize locationManager;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
[self.mapView setShowsUserLocation:YES];
MKCoordinateRegion newRegion ;
newRegion.center.latitude = 50.080635;
newRegion.center.longitude = 8.518717;
newRegion.span.latitudeDelta = 15.5;
newRegion.span.longitudeDelta = 15.5;
[mapView setRegion:newRegion animated:YES];
NSString *path = [[NSBundle mainBundle] pathForResource:#"Rezepte" ofType:#"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSArray *anns = [dict objectForKey:#"myRecipes"];
for(int i = 0; i < [anns count]; i++) {
float realLatitude = [[[anns objectAtIndex:i] objectForKey:#"latitude"] floatValue];
float realLongitude = [[[anns objectAtIndex:i] objectForKey:#"longitude"] floatValue];
MapViewAnnotation *myAnnotation = [[MapViewAnnotation alloc] init];
CLLocationCoordinate2D theCoordinate;
theCoordinate.latitude = realLatitude;
theCoordinate.longitude = realLongitude;
myAnnotation.coordinate = theCoordinate;
myAnnotation.title = [[anns objectAtIndex:i] objectForKey:#"blogname"];
myAnnotation.subtitle = [[anns objectAtIndex:i] objectForKey:#"blogger"];
[mapView addAnnotation:myAnnotation];
}
}
-(MKAnnotationView *)mapView:(MKMapView *)view viewForAnnotation:(id<MKAnnotation>)annotation {
MKPinAnnotationView *pin = nil;
if ([annotation isKindOfClass:[MapViewAnnotation class]]) {
NSString *pinIdentifier = #"myPin";
pin = (MKPinAnnotationView*)[view dequeueReusableAnnotationViewWithIdentifier:pinIdentifier];
if (!pin) {
pin = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pinIdentifier];
pin.image = [UIImage imageNamed:#"pin2.png"];
pin.canShowCallout = YES;
pin.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
}
}
return pin;
}
//if Button pressed
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control{
[self performSegueWithIdentifier:#"showPinDetails" sender:self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showPinDetails"]) {
// SetCardController *scc = [segue destinationViewController];
}
}
When you performSegueWithIdentifier:sender from a callout inside annotationView:view, the sender can be the view.annotation property, which uniquely identifies the callout that the user just tapped.
I believe you didn't set the identifier for the Segue in Interface Builder. I tried your code and it worked for me (Xcode 4.4 iOS 5.1 SDK)
The above two answers help, however don't help you identify the unique pins details that I am assuming are part of your p-list.
All Views inherit a the property of a Tag. It can used this to hold a pin index (or key)and therefore pass this to the destination View Controller to uniquely identify the data you hold.
As your button in the call-out view inherits from view you can tag it, and pass the index when its active in the method didselectAnnotationView. The if statement used de-selects the User location pin.
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
if (![(PointAnnotation *)view.annotation isKindOfClass:[MKUserLocation class]])
{
PointAnnotation *myAnn = (PointAnnotation *)view.annotation;
detailButton.tag = myAnn.pinIndex;
NSLog (#"Pinindex = %d", myAnn.pinIndex);
}
}
The detailButton.tag can now be used as a parameter in segue selection.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Post data to destination VC
if ([[segue identifier] isEqualToString:#"clubsToDetail"])
{
ClubsMasterData *current = [[ClubsMasterxmlParser ClubsMasterDatas] objectAtIndex:detailButton.tag];
ClubsDetailViewController *DVC = [[ClubsDetailViewController alloc] init];
DVC = [segue destinationViewController];
DVC.linkURL = current.linkURL;
DVC.distance = current.distance;
}
}
Here I indexed an Array rather than a Plist, but the principal is the same.