Current location query on click event - iphone

I am Showing Australia continent when my Map application launch. I have one button on which I want to set coding for current location and zoom in to that location after pressing butoon. I am getting current latitude & longitude and able to pass in Web-service url. I did following coding
- (void)viewDidLoad
{
//to set the australia region
CLLocationCoordinate2D AusLoc = {-19.048230,133.685730};
MKCoordinateSpan AusSpan = MKCoordinateSpanMake(45, 45);
MKCoordinateRegion AusRegion = MKCoordinateRegionMake(AusLoc, AusSpan);
mapView.region = AusRegion;
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[locationManager startUpdatingLocation]; }
and
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
if((fabs(newLocation.coordinate.latitude) > 0.001) || (fabs(newLocation.coordinate.longitude) > 0.001)) {
NSLog(#"Got location %f,%f", newLocation.coordinate.latitude, newLocation.coordinate.longitude);
if (currentLocation != nil) {
[currentLocation release];
}
currentLocation = newLocation;
[currentLocation retain];
}
NSString *lati=[NSString stringWithFormat:#"%f", newLocation.coordinate.latitude];
NSString *longi=[NSString stringWithFormat:#"%f", newLocation.coordinate.longitude];
}
on Search button(web service calling)
NSString *url = [NSString stringWithFormat:#"http://.....url...../hespdirectory/phpsqlsearch_genxml.php?lat=%f&lng=%f&radius=%f",locationManager.location.coordinate.latitude,locationManager.location.coordinate.longitude,radius];
Updated with coding:
- (IBAction) showAddress {
if (locationManager.location == nil)
{
NSLog(#"user location not found yet or service disabled/denied");
}
else
{
// Change map region using span (degrees)...
MKCoordinateSpan span = MKCoordinateSpanMake(0.001, 0.001);
MKCoordinateRegion region = MKCoordinateRegionMake
(locationManager.location.coordinate, span);
[mapView setRegion:region animated:YES];
}
}
When I set mapView.showUserLocation = YES; it shows current location when map application launch that is before tapping button. I am confused with previous answer. So What code should I put under button click event to show current location and also suggest If there is any change to pass current Lati and longi in web service url after giving coding for click event. Thanks in advance
Edited:-
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{
MKPinAnnotationView *annView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#""];
annView.pinColor = MKPinAnnotationColorGreen;
//annView.animatesDrop=TRUE;
annView.canShowCallout = YES;
annView.calloutOffset = CGPointMake(-5, 5);
annView.enabled = YES;
annView.image = [UIImage imageNamed:#"flagg.png"];
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
annView.rightCalloutAccessoryView = rightButton;
NSLog(#"Created annotation at: %f %f", ((CustomPlacemark*)annotation).coordinate.latitude, ((CustomPlacemark*)annotation).coordinate.longitude);
[annView addObserver:self
forKeyPath:#"selected"
options:NSKeyValueObservingOptionNew
context:#"GMAP_ANNOTATION_SELECTED"];
[annView autorelease];
return annView;
}
//return nil;
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context{
NSString *action = (NSString*)context;
// We only want to zoom to location when the annotation is actaully selected. This will trigger also for when it's deselected
if([[change valueForKey:#"new"] intValue] == 1 && [action isEqualToString:#"GMAP_ANNOTATION_SELECTED"])
{
if([((MKAnnotationView*) object).annotation isKindOfClass:[CustomPlacemark class]])
{
CustomPlacemark *place = ((MKAnnotationView*) object).annotation;
// Zoom into the location
[mapView setRegion:place.coordinateRegion animated:TRUE];
NSLog(#"annotation selected: %f %f", ((MKAnnotationView*) object).annotation.coordinate.latitude, ((MKAnnotationView*) object).annotation.coordinate.longitude);
}
}
}
In Search button(calling webservice)
CLLocationCoordinate2D location;
//currentLocation = newLocation;
float radius = [[arrayNo objectAtIndex:[pickerView selectedRowInComponent:0]] floatValue];
//NSURL *url = [[NSURL alloc] initWithString:#"http://www.hettich.com.au/hespdirectory/phpsqlsearch_genxml.php?lat=-33.853468&lng=150.94042160000004&radius=5"];
NSString *url = [NSString stringWithFormat:#"http://www.hettich.com.au/hespdirectory/phpsqlsearch_genxml.php?lat=%f&lng=%f&radius=%f",locationManager.location.coordinate.latitude,locationManager.location.coordinate.longitude,radius];
//NSLog(#"NSString *url");
NSLog(#"%#", url);
NSURL *URL = [NSURL URLWithString:url];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:URL];
//Initialize the delegate.
XMLParser *parser = [[XMLParser alloc] initXMLParser];
//Set delegate
[xmlParser setDelegate:parser];
//Start parsing the XML file.
BOOL success = [xmlParser parse];
if(success)
{ resultButton.userInteractionEnabled = YES;
// NSMutableArray* annotations = [[NSMutableArray alloc] init];
for (int i = 0; i < [appDelegate.markers count]; i++)
{
marker *aMarker = [appDelegate.markers objectAtIndex:i];
location.latitude = [aMarker.lat floatValue];
location.longitude =[aMarker.lng floatValue];
AddressAnnotation *annob = [[AddressAnnotation alloc] initWithCoordinate:location];
annob.title = aMarker.name;
annob.subTitle = aMarker.address;
[mapView addAnnotation:annob];
[annob release];
CLLocationCoordinate2D ausLoc = {location.latitude,location.longitude}; //for zoom in the showroom results region
MKCoordinateSpan ausSpan = MKCoordinateSpanMake(0.108889, 0.169922);
MKCoordinateRegion ausRegion = MKCoordinateRegionMake(ausLoc, ausSpan);
NSLog(#"No Errors");
mapView.region = ausRegion;
}
}

In your button tapped method, you should first check if the location manager has obtained a location and then set the map's center or region to the user's location:
if (locationManager.location == nil)
{
NSLog(#"user location not found yet or service disabled/denied");
}
else
{
// Change map center (preserving current zoom level)...
[mapView setCenterCoordinate:locationManager.location.coordinate animated:YES];
// --OR--
// Change map region using distance (meters)...
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance
(locationManager.location.coordinate, 1000, 1000);
[mapView setRegion:region animated:YES];
// --OR--
// Change map region using span (degrees)...
MKCoordinateSpan span = MKCoordinateSpanMake(0.001, 0.001);
MKCoordinateRegion region = MKCoordinateRegionMake
(locationManager.location.coordinate, span);
[mapView setRegion:region animated:YES];
}
In the didUpdateToLocation method, you are setting a "currentLocation" variable but I don't see a need for it. The locationManager already has a location property.
In any case, only considering absolute latitudes or longitudes greater than 0.001 as "valid" is incorrect because a) it excludes locations near the equator or prime meridian (even though you're only interested in Australia this logic is the wrong way to go), and b) it's better instead to check if newLocation itself is nil.

Related

how to hide current Location annotation from mkmapview

In my application i have used the MKmapview,I want to hide the user current location annotation point,Here my code
- (void)viewDidLoad
{
[super viewDidLoad];
appDel=(AppDelegate *)[UIApplication sharedApplication].delegate;
DatabaseController *dbObj=[[DatabaseController alloc] init];
NSString *query=[NSString stringWithFormat:#"select * from petBoundarySettings where petId=%#",self.petID];
NSMutableArray *alertSettingArray=[dbObj getPetAlertSerrings:query :[appDel getDBPath]];
if([alertSettingArray count]>0){
distance=[[[alertSettingArray objectAtIndex:0] objectForKey:#"distance"] integerValue];
address=[[alertSettingArray objectAtIndex:0] objectForKey:#"address"];
lat2=[[alertSettingArray objectAtIndex:0] objectForKey:#"lat"] ;
lon2=[[alertSettingArray objectAtIndex:0] objectForKey:#"lang"] ;
}
UIImageView *imageNav = [[UIImageView alloc] initWithImage: [UIImage imageNamed: #"sml-cat_03.png"]];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:imageNav];
[imageNav release];
[dbObj release];
MKCoordinateSpan span;
span.latitudeDelta=.01;
span.longitudeDelta=.01;
MKCoordinateRegion region;
//distance=appDel.alertDistance;
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = nil;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
[locationManager startUpdatingLocation];
currentAnnotation=[[MyAnnotations alloc]init];
NSLog(#"GL%f",appDel.getlat);
NSLog(#"GN%f",appDel.getlon);
regionCoordinate.latitude =[lat2 floatValue];
regionCoordinate.longitude = [lon2 floatValue];
currentAnnotation.coordinate=regionCoordinate;
currentAnnotation.title=#"Boundary Location";
currentAnnotation.subtitle=appDel.address;
region.center=CLLocationCoordinate2DMake(regionCoordinate.latitude,regionCoordinate.longitude);
region.span=span;
[_myMapView setRegion:region animated:YES];
[_myMapView regionThatFits:region];
region1=region;
petAnnotation=[[MyAnnotations alloc]init];
petCoordinate.latitude = +11.028549739;
petCoordinate.longitude = +76.89644586;
petAnnotation.coordinate=petCoordinate;
petAnnotation.title=#"My Pet Location";
petAnnotation.subtitle=#"Vadavalli";
MKCircle *circle = [MKCircle circleWithCenterCoordinate:regionCoordinate radius:distance];
[_myMapView addOverlay:circle];
CLLocation *whereIAm = [locationManager location];
NSLog(#"MI%#",whereIAm);
[_myMapView addAnnotation:currentAnnotation];
MKMapPoint p1 = MKMapPointForCoordinate(regionCoordinate);
MKMapPoint p2 = MKMapPointForCoordinate(petCoordinate);
CLLocationDistance dist = MKMetersBetweenMapPoints(p1, p2);
i=0;
[self getPetData];
timer= [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:#selector(getPetData) userInfo:nil repeats:YES];
if(appDel.checkGPS==NO)
{
[self getPetDataFromGPS];
}
}
How to hide the current location from mkmapview,Please help me to sort out.
MKMapView has a property named showsUserLocation that you can set to determine whether the user's location can be displayed. However, I see that you're not setting it in code, and the default value is NO.
If you're using a Xib or Storyboard, check the MKMapView in there, as there is a checkbox for this behaviour in the attributes inspector. (Shows User Location)

show user location on a map and stop location

Here is my goal:
I have to show the user location with his address on a map every time he open the view that has the MapView and then stop location to save battery. So far i can do it, but if the user moves to another area and enter the view (after leave it) the location does not change.
Here is my code:
- (void)viewDidLoad
{
mapView.mapType = MKMapTypeStandard;
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated{
if(!self.locationManager){
self.locationManager = [[CLLocationManager alloc] init];
}
[self.locationManager startUpdatingLocation];
}
-(void)viewDidDisappear:(BOOL)animated{
self.locationManager = nil;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
MKCoordinateRegion viewRegion =
MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 2000, 2000);
MKCoordinateRegion adjustedRegion = [mapView regionThatFits:viewRegion];
[mapView setRegion:adjustedRegion animated:YES];
[manager stopUpdatingLocation];
MKReverseGeocoder *geocoder = [[MKReverseGeocoder alloc]
initWithCoordinate:newLocation.coordinate];
geocoder.delegate = self;
[geocoder start];
}
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark {
MapLocation *annotation = [[MapLocation alloc] init];
annotation.streetAddress = placemark.thoroughfare;
annotation.city = placemark.locality;
annotation.state = placemark.administrativeArea;
annotation.zip = placemark.postalCode;
annotation.coordinate = geocoder.coordinate;
[mapView addAnnotation:annotation];
geocoder.delegate = nil;
}
- (void)openCallout:(id<MKAnnotation>)annotation {
[mapView selectAnnotation:annotation animated:YES];
}
- (MKAnnotationView *) mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>) annotation {
static NSString *placemarkIdentifier = #"Map Location Identifier";
if ([annotation isKindOfClass:[MapLocation class]]) {
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[theMapView dequeueReusableAnnotationViewWithIdentifier:placemarkIdentifier];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:placemarkIdentifier];
}
else{
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.image = [UIImage imageNamed:#"rescue"];
[self performSelector:#selector(openCallout:) withObject:annotation afterDelay:0.5];
return annotationView;
}
return nil;
}
I have a CLLocationManager on another view that get user location without a map (here the location is working just fine). If a start the location on that view and go back to the view with the map it's is updated. Why that?
Any ideias?
- (void)loadView {
MKMapView *mv = [[MKMapView alloc]init];
mapView.showsUserLocation=YES;
mv.delegate=self;
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
[mapView setCenterCoordinate:mapView.userLocation.location.coordinate animated:YES];
mapView.showsUserLocation=NO;
}
well to display it on the map
MKMapView *mv = [[MKMapView alloc]init];
CLLocationCoordinate2D c = CLLocationCoordinate2DMake(locationManager.location.coordinate.latitude, locationManager.location.coordinate.longitude);
[mv setCenterCoordinate:c animated:YES];
and to stop updating
[locationManager stopUpdatingLocation];

How do I set map zoom based on nearest pin to current location

Right now I am setting my region based on users current location. I would like to now set the zoom level so I can see the users current location and the nearest pin that is being pulled in via json.
Not until run time will the app know the number of pins or the locations of said pins.
Here is what I have so far.
#implementation LocationsViewController
#synthesize mapView;
#synthesize locationManager;
#synthesize phone;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
self.title = NSLocalizedString(#"Locations", #"Locations");
self.tabBarItem.image = [UIImage imageNamed:#"locations"];
}
return self;
}
- (void)dealloc
{
[super dealloc];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
//Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"New latitude: %f", newLocation.coordinate.latitude);
NSLog(#"New longitude: %f", newLocation.coordinate.longitude);
MKCoordinateRegion region;
region.center.latitude =newLocation.coordinate.latitude;
region.center.longitude= newLocation.coordinate.longitude;
region.span.longitudeDelta=0.2;
region.span.latitudeDelta =0.2;
[mapView setRegion:region animated:YES];
[mapView setDelegate:self];
//[locationManager stopUpdatingLocation];
}
-(void)viewDidDisappear:(BOOL)animated
{
[locationManager stopUpdatingLocation];
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[locationManager startUpdatingLocation];
if([self connectedToNetwork] != YES)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"OH NO!" message:#"To get the latest information you need a data or wi-fi connection" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
else
{
[mapView removeAnnotations:mapView.annotations];
NSString *urlString = [NSString stringWithFormat:#"http://www.mywebsite.com/json.json"];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [NSData dataWithContentsOfURL:url];
NSError *error;
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
for(id key in json) {
id value = [json objectForKey:key];
NSString *titlePin = [value valueForKey:#"address"];
NSString *address = [value valueForKey:#"title"];
NSString *latitude = [value valueForKey:#"latitude"];
NSString *longitude = [value valueForKey:#"longitude"];
NSArray* foo = [address componentsSeparatedByString: #":"];
NSString* address2 = [foo objectAtIndex: 0];
phone = [foo objectAtIndex: 1];
double myLatitude = [latitude doubleValue];
double myLongitude = [longitude doubleValue];
MKCoordinateRegion location1;
location1.center.latitude =myLatitude;
location1.center.longitude= myLongitude;
location1.span.longitudeDelta=0.1;
location1.span.latitudeDelta =0.1;
MapAnnotation *ann1 =[[[MapAnnotation alloc] init] autorelease];
ann1.title=[NSString stringWithFormat:#"%#",titlePin];
ann1.subtitle=[NSString stringWithFormat:#"%#",address2];
ann1.phone=[NSString stringWithFormat:#"%#",phone];
ann1.coordinate= location1.center;
[mapView addAnnotation:ann1];
[phone retain];
}
}
}
-(MKAnnotationView *) mapView:(MKMapView *)mapView2 viewForAnnotation:(id<MKAnnotation>)annotation {
if (annotation == mapView2.userLocation) {
return nil;
}else{
MKPinAnnotationView *MyPin=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"current"];
MyPin.pinColor = MKPinAnnotationColorPurple;
UIButton *advertButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
[advertButton setImage:[UIImage imageNamed:#"mapphone"] forState:UIControlStateNormal];
[advertButton addTarget:self action:#selector(button:) forControlEvents:UIControlEventTouchUpInside];
MyPin.rightCalloutAccessoryView = advertButton;
MyPin.draggable = NO;
MyPin.highlighted = YES;
MyPin.animatesDrop=TRUE;
MyPin.canShowCallout = YES;
return MyPin;
}
}
-(void)button:(id)sender {
UIButton *button = (UIButton *)sender;
MKPinAnnotationView *annotationView = (MKPinAnnotationView*)button.superview.superview;
MapAnnotation *mapAnnotation = annotationView.annotation;
UIDevice *device = [UIDevice currentDevice];
if ([[device model] isEqualToString:#"iPhone"] ) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:#"tel:%#",mapAnnotation.phone]]];
} else {
UIAlertView *Notpermitted=[[UIAlertView alloc] initWithTitle:mapAnnotation.phone message:#"Your device doesn't support this feature." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[Notpermitted show];
[Notpermitted release];
}
}
- (BOOL) connectedToNetwork
{
Reachability *r = [Reachability reachabilityWithHostName:#"www.google.com"];
NetworkStatus internetStatus = [r currentReachabilityStatus];
BOOL internet;
if ((internetStatus != ReachableViaWiFi) && (internetStatus != ReachableViaWWAN)) {
internet = NO;
} else {
internet = YES;
}
return internet;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
#end
I did something similar, but based on two annotations, not the user's location. You should be able to replace mapView.centerCoordinate with mapView.userLocation.coordinate.
in viewForAnnotation:
CLLocation *centerLoc = [[CLLocation alloc] initWithLatitude:mapView.centerCoordinate.latitude longitude:mapView.centerCoordinate.longitude];
CLLocation *loc2 = [[CLLocation alloc] initWithLatitude:[annotation coordinate].latitude longitude:[annotation coordinate].longitude];
CLLocationDistance distance = [loc2 distanceFromLocation:centerLoc];
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(mapView.centerCoordinate, distance*2, distance*2);
MKCoordinateRegion adjustedRegion = [mapView regionThatFits:viewRegion];
[mapView setRegion:adjustedRegion animated:YES];
Note, this code will re-calc the zoom level each time you add an annotation. You may need to save the distance and only change the map if the new distance is greater than the prior distance.

MKAnnotationView issue where my pins show up initially then disappear?

I am attempting to debug an issue with my code where the pins on my MKAnnotationView initially show up on first call for a second, but when the map zooms in on the location, all the annotations except for the user location disappears. Can someone point me to a flaw in my logic?
Below is the code being used. AddPlacemark is used to get the locations of all my annotations then the MKAnnotationView should show them all on the map. Like I said, when the map first appears the annotations all show, but when the map zooms in on the location of the user, all my other annotations disappear. I believe this issue only started occurring when I updated my Xcode so that I could test on iOS 6 and get the simulator for the iPhone 5.
- (void)AddPlacemark {
if([allplacemarkarray count]>0) {
[mapView removeAnnotations:allplacemarkarray];
[allplacemarkarray removeAllObjects];
}
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta=0.2;
span.longitudeDelta=0.2;
CLLocationCoordinate2D location1;
location1.latitude = appdel.MyCurrentLocation.latitude;
location1.longitude = appdel.MyCurrentLocation.longitude;
region.span = span;
region.center = location1;
Placemark *addAnnotation = [[[Placemark alloc] initWithCoordinate:location1] retain];
[mapView addAnnotation:addAnnotation];
[allplacemarkarray addObject:addAnnotation];
[addAnnotation release];
if(alllocationArray) {
for(int i=0;i<[alllocationArray count];i++) {
NSDictionary *locationdict=[alllocationArray objectAtIndex:i];
CLLocationCoordinate2D location;
location.latitude = [[locationdict objectForKey:#"VLATITUDE"] floatValue];
location.longitude =[[locationdict objectForKey:#"LONGITUDE"]floatValue];
region.span=span;
region.center=location;
Placemark *addAnnotation = [[[Placemark alloc] initWithCoordinate:location] retain];
[allplacemarkarray addObject:addAnnotation];
addAnnotation.titletext = [locationdict objectForKey:#"NAME"];
addAnnotation.logoText = [locationdict objectForKey:#"LOGO"];
NSString *add1=[locationdict objectForKey:#"ADDR1"];
NSString *add2=[locationdict objectForKey:#"ADDR2"];
NSString *city=[locationdict objectForKey:#"CITY"];
NSString *state=[locationdict objectForKey:#"STATE"];
NSString *zip =[locationdict objectForKey:#"ZIP"];
addAnnotation.subtitletext=[NSString stringWithFormat:#"%# %# %#, %# %#",add1,add2,city,state,zip];
[addAnnotation setPlacemarkId:[NSNumber numberWithInt:i]];
[mapView addAnnotation:addAnnotation];
[addAnnotation release];
}
[mapView setRegion:region animated:TRUE];
[mapView regionThatFits:region];
}
}
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(Placemark *) annotation {
MKPinAnnotationView *annView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"MyPin"];
annView.animatesDrop = TRUE;
annView.canShowCallout = YES;
[annView setSelected:YES];
UIImage *pinImage = [UIImage imageNamed:annotation.logoText];
UIImageView *logoView = [[UIImageView alloc] initWithImage:pinImage];
logoView.frame = CGRectMake(-23, -6, 63, 48);
UIButton *myDetailButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
myDetailButton.frame = CGRectMake(0, 0, 23, 23);
myDetailButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
myDetailButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
[myDetailButton addTarget:self action:#selector(checkButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
[myDetailButton setTag:[annotation.placemarkId intValue]];
annView.rightCalloutAccessoryView=myDetailButton;
if(annotation.coordinate.latitude == appdel.MyCurrentLocation.latitude && annotation.coordinate.longitude == appdel.MyCurrentLocation.longitude) {
annView.pinColor = MKPinAnnotationColorRed;
} else if ([annotation.logo isEqualToString:#""]) {
annView.pinColor = MKPinAnnotationColorPurple;
} else {
[annView addSubview:logoView];
}
annView.calloutOffset = CGPointMake(-5, 5);
return annView;
}
This question is actually not due to bad code in the app. Sorry about that! It turns out my backend code that feeds information to this logic was bad.

Calculating routes with multiple pins

In my application I have a mapView with several custom pins.
I'm trying to do this: On the showCallout an AlertView appears and tells if you want to calculate the route. This works but just for one location. Or better, only one method gets called, so I've only one destination.
Here's my code (I have 9 destinations, but I post only 2 to make the code shorter):
- (void)viewDidLoad
{
[super viewDidLoad];
[mapView setMapType:MKMapTypeStandard];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];
[mapView setDelegate:(id)self];
MKCoordinateRegion TavernaCongiura = { {0.0, 0.0} , {0.0, 0.0} };
TavernaCongiura.center.latitude = 40.380784;
TavernaCongiura.center.longitude = 15.541373;
TavernaCongiura.span.longitudeDelta = 0.004f;
TavernaCongiura.span.latitudeDelta = 0.004f;
[mapView setRegion:TavernaCongiura animated:YES];
mapView.showsUserLocation = YES;
TeggianoAnnotation *ann0 = [[TeggianoAnnotation alloc] init];
ann0.title = #"Taverna de la Congiura";
ann0.subtitle = #"Antipasto";
ann0.coordinate = TavernaCongiura.center;
[mapView addAnnotation: ann0];
MKCoordinateRegion TavernaDeiMori = { {0.0, 0.0} , {0.0, 0.0} };
TavernaDeiMori.center.latitude = 40.380535;
TavernaDeiMori.center.longitude = 15.542028;
TavernaDeiMori.span.longitudeDelta = 0.004f;
TavernaDeiMori.span.latitudeDelta = 0.004f;
[mapView setRegion:TavernaDeiMori animated:YES];
TeggianoAnnotation *ann1 = [[TeggianoAnnotation alloc] init];
ann1.title = #"Taverna dei Mori";
ann1.subtitle = #"Parmatieddi";
ann1.coordinate = TavernaDeiMori.center;
[mapView addAnnotation: ann1];
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation
*)newLocation fromLocation:(CLLocation *)oldLocation {
if (newLocation.horizontalAccuracy == oldLocation.horizontalAccuracy) {
[self->locationManager stopUpdatingLocation];
CLLocationCoordinate2D coords = newLocation.coordinate;
NSString *stringURL = [NSString stringWithFormat:#"http://maps.google.com
/maps?saddr=%g,%g&daddr=40.380784,15.541373", coords.latitude, coords.longitude];
NSURL *url = [NSURL URLWithString:stringURL];
[[UIApplication sharedApplication] openURL:url];
}
}
- (void)locationManagerMori:(CLLocationManager *)manager didUpdateToLocation:
(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
if (newLocation.horizontalAccuracy == oldLocation.horizontalAccuracy) {
[self->locationManager stopUpdatingLocation];
CLLocationCoordinate2D coords = newLocation.coordinate;
NSString *stringURL = [NSString stringWithFormat:#"http://maps.google.com
/maps?saddr=%g,%g&daddr=40.380535,15.542028", coords.latitude, coords.longitude];
NSURL *url = [NSURL URLWithString:stringURL];
[[UIApplication sharedApplication] openURL:url];
}
}
-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:
(id<MKAnnotation>)annotation {
MKAnnotationView *MyPin=[[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:#"current"];
UIButton *advertButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
if ([[annotation title] isEqualToString:#"Taverna de la Congiura"]) {
[advertButton addTarget:self action:#selector(buttonCongiura:)
forControlEvents:UIControlEventTouchUpInside];
MyPin.image = [UIImage imageNamed:#"CongiuraMappa.png"];
}
if ([[annotation title] isEqualToString:#"Taverna dei Mori"]) {
[advertButton addTarget:self action:#selector(buttonMori:)
forControlEvents:UIControlEventTouchUpInside];
MyPin.image = [UIImage imageNamed:#"MoriMappa.png"];
}
MyPin.rightCalloutAccessoryView = advertButton;
MyPin.draggable = NO;
MyPin.highlighted = YES;
MyPin.canShowCallout = YES;
return MyPin;
}
-(void)buttonCongiura:(id)sender {
UIAlertView *alertViewCongiura;
alertViewCongiura = [[UIAlertView alloc] initWithTitle:#"Taverna de la Congiura"
message:#"Calcola Percorso" delegate:self cancelButtonTitle:#"Annulla"
otherButtonTitles:#"Calcola", nil];
[alertViewCongiura show];
}
-(void)buttonMori:(id)sender {
UIAlertView *alertViewMori;
alertViewMori = [[UIAlertView alloc] initWithTitle:#"Taverna dei Mori"
message:#"Calcola Percorso" delegate:self cancelButtonTitle:#"Annulla"
otherButtonTitles:#"Calcola", nil];
[alertViewMori show];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1) {
self->locationManager = [[CLLocationManager alloc] init];
self->locationManager.delegate = (id)self;
[self->locationManager startUpdatingLocation];
}
if (buttonIndex == 2) {
self->locationManagerMori = [[CLLocationManager alloc] init];
self->locationManagerMori.delegate = (id)self;
[self->locationManagerMori startUpdatingLocation];
}
}
The problem is that only the first
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation
*)newLocation fromLocation:(CLLocation *)oldLocation
is called.
You can't use a different name for the delegate methods for each of the location manager instances you are using. Each location manager will still call the methods defined by the CLLocationManagerDelegate protocol.
You could check which manager is calling by checking if the manager parameter is equal to one of the instances you are creating (eg. if (manager == locationManagerMori)).
But you don't need to create a separate location manager instance for each annotation in the first place.
Instead, keep just one location manager instance and in the delegate method, you can find out what the currently selected annotation is and use its coordinates in the url string. For example:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
if (newLocation.horizontalAccuracy == oldLocation.horizontalAccuracy)
//the above if-condition looks a little suspicious by the way
{
if (mapView.selectedAnnotations.count == 0)
{
//no annotation selected, do nothing
return;
}
//there can only be one selected annotation so get the one at index 0
id<MKAnnotation> selectedAnnotation =
[mapView.selectedAnnotations objectAtIndex:0];
[self->locationManager stopUpdatingLocation];
CLLocationCoordinate2D coords = newLocation.coordinate;
NSString *stringURL = [NSString stringWithFormat:
#"http://maps.google.com/maps?saddr=%g,%g&daddr=%g,%g",
coords.latitude, coords.longitude,
selectedAnnotation.coordinate.latitude,
selectedAnnotation.coordinate.longitude];
NSURL *url = [NSURL URLWithString:stringURL];
//stop updating location to avoid possible endless loop
//when user comes back to this app...
[manager stopUpdatingLocation];
[[UIApplication sharedApplication] openURL:url];
}
}
You also don't need a separate button action method for each annotation. You can just create one button action method and use the same technique to get the selected annotation.
Another issue is in the alert view clickedButtonAtIndex method. You seem to be checking which annotation it is by looking at the alert view's button index. That index will be either the Annulla or Calcola button (not which annotation).
Since you won't need to create a separate location manager for each annotation, you won't need to know which annotation the alert view is for. You just need to check whether the user tapped Annulla or Calcola:
if (buttonIndex == alertView.firstOtherButtonIndex)
{
self->locationManager = [[CLLocationManager alloc] init];
self->locationManager.delegate = (id)self;
self->locationManager startUpdatingLocation];
}