i want to get annotation title & subtitle from this method.
what the way go get that.
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
//NSString * title = [annotations title];
}
The view has an annotation property that you can use which will return the annotation you originally used when creating the view.
Related
I have a project where I show directions between current location and another location on a map (MapKit)
All works well. And I can get alternative routes.
request.requestsAlternateRoutes = YES;
But when the user tap on a route I show an annotation with distance and some other info. I want to pass this spesific route to another view. How can I achieve that? Like the original Map app on iOS. I can get different routes, and tap on a route to get direction details.
I have googled a lot, and the closest example is this:
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
// Now handle the result
if (error) {
NSLog(#"There was an error getting your directions");
return;
}
_currentRoute = [response.routes firstObject];
But _currentRoute is the first one. I want to let the user select currentRoute on tap on the map.
I figured it out. Not so elegant, but it does the job.
Make an ivar - NSMutableArray *routeArray in the header file.
I also have a MKMapView outlet in my header.
In my getDirections method, I tagged the MKMapView instance with a counter and added the route object to the routeArray.
When the delegate for making the Annotation is run, I can tag the anntotationView with the mapView.tag.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
When I tap on the annotation:
(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
I pass the view.tag to my segue.
NSLog(#"Counter tag: %ld", (long)view.tag);
[self performSegueWithIdentifier:#"detaljer" sender:view];
I can then pass my selected route to my new view.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
WeatherTableViewController *routeController =
[segue destinationViewController];
long row = [sender tag];
MKRoute *route = routeArray[row];
routeController.selectedRoute = route;
}
I'm using MapKit and I have 2 callout accessories in my pins.
I'm trying to implement a button for updating the pin's title and one for deleting the pin.
Right now, anytime I press a button on the annotation, it only deletes the pin.
How do I get it to respond differently for the right button vs the left button?
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
id <MKAnnotation> annotation = [view annotation];
if ([annotation isKindOfClass:[MKPointAnnotation class]])
{
NSLog(#"Clicked");
if(view.rightCalloutAccessoryView){
[self.mapView removeAnnotation:annotation];
}
else{
float lat= annotation.coordinate.latitude;
float longitude = annotation.coordinate.longitude;
[self.mapView removeAnnotation:annotation];
MKPointAnnotation *pointAnnotation = [[MKPointAnnotation alloc] init];
pointAnnotation.title = _titleOut.text;
pointAnnotation.subtitle = _subtitle.text;
pointAnnotation.coordinate = CLLocationCoordinate2DMake(lat, longitude);
[self.mapView addAnnotation:pointAnnotation];
}
}
}
This line:
if(view.rightCalloutAccessoryView){
says essentially "if view.rightCalloutAccessoryView is not nil".
Since you are setting the right-side accessory on all annotation views, that if condition will always be true and so tapping either accessory will execute the code inside that if which is to remove the annotation.
Instead, you want to check what button or control was tapped in this specific case of the delegate method being called (not whether the view has a right-side accessory defined).
Fortunately, the delegate method passes exactly what control was tapped in the control parameter.
The control parameter can be directly compared against the view's right/left accessory view to tell which was tapped:
if (control == view.rightCalloutAccessoryView) {
Some unrelated points:
The latitude and longitude properties in annotations are of type CLLocationDegrees (aka double) which has higher precision than float so to avoid losing accuracy, use CLLocationDegrees or double:
CLLocationDegrees lat= annotation.coordinate.latitude;
The MKPointAnnotation allows you to change the title directly (it's not read-only like the default id<MKAnnotation>) so you don't need to remove and create a new annotation. It simplifies the code a bit:
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
if ([view.annotation isKindOfClass:[MKPointAnnotation class]])
{
NSLog(#"Clicked");
if (control == view.rightCalloutAccessoryView) {
[self.mapView removeAnnotation:view.annotation];
}
else {
// Cast view.annotation as an MKPointAnnotation
// (which we know it is) so that compiler sees
// title is read-write instead of the
// default id<MKAnnotation> which is read-only.
MKPointAnnotation *pa = (MKPointAnnotation *)view.annotation;
pa.title = _titleOut.text;
pa.subtitle = _subtitle.text;
//If you want callout to be closed automatically after
//title is changed, uncomment the line below:
//[mapView deselectAnnotation:pa animated:YES];
}
}
}
I have many custom annotations to whom I gave the property (NameTable and ID). I set this property before AddAnnotation the moment of creation, but these property in the delegate methods are no longer visible. I have multiple annotation associated with elements of tables taken from a database. How can I make them visible in the delegate methods?
- (void)viewDidLoad
{
//......
for(int i=0; i<6; i++){ //loop for create multiple annotations
AnnotationCustom *annotationIcone =[[AnnotationCustom alloc]initWithCoordinates:coord
title:self.myTable.title subTitle:self.myTable.address];
annotationIcone.nameTable = [NSString stringWithFormat:#"%#", self.myTableName];
annotationIcone.ID = i+1;
[self.mapView addAnnotation: annotationIcone;
//.....
}
But in the delegate methods:
(MKAnnotationView *)mapView:(MKMapView *)mapview viewForAnnotation:(id
<MKAnnotation>)annotation
{
NSLog(#"The name of table is:#"%#", annotation.nameTable);
//property 'nameTable' not found on object of type '_strong id <MKAnnotation>
NSLog (#The name of table is:#%#", annotation.ID);
//property 'ID' not found on object of type '_strong id <MKAnnotation>
//......
}
In another method:
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
NSLog(#"The name of table is %#", self.myTableName);
// here I get the name of last table open and not the name of table selected
}
In viewForAnnotation, you need to tell the compiler that the annotation is actually an AnnotationCustom object.
So you first need to do this:
AnnotationCustom *annotationCustom = (AnnotationCustom *)annotation;
and then try to access the nameTable property..
In the didSelectAnnotationView method, if what you want is to get the nameTable value of the annotation selected you need to do the following:
AnnotationCustom *annotationCustomSelected = (AnnotationCustom *)view.annotation;
NSLog(#"table name of annotation selected: %#", annotationCustomSelected.nameTable);
I got an app with MKMapView and large number of pins on this map.
Every pin got rightCalloutAccessoryView. I create it in this way:
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = rightButton;
How should i know, which pin was tapped? Thnx
In the showDetails: method, you can get the pin tapped from the map view's selectedAnnotations array. Even though the property is an NSArray, just get the first item in the array since the map view only allows one pin to be selected at a time:
//To be safe, may want to check that array has at least one item first.
id<MKAnnotation> ann = [[mapView selectedAnnotations] objectAtIndex:0];
// OR if you have custom annotation class with other properties...
// (in this case may also want to check class of object first)
YourAnnotationClass *ann = [[mapView selectedAnnotations] objectAtIndex:0];
NSLog(#"ann.title = %#", ann.title);
By the way, instead of doing addTarget and implementing a custom method, you can use the map view's calloutAccessoryControlTapped delegate method. The annotation tapped is available in the view parameter:
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control
{
NSLog(#"ann.title = %#", view.annotation.title);
}
Make sure you remove the addTarget from viewForAnnotation if you use calloutAccessoryControlTapped.
Ok, so I have a map view that has a bunch of annotations on it. Certain annotations when selected need to display extended info in a small table view which i am doing by resizing the mapview to half screen and animating into view a table in the bottom half. If another annotation is selected that doesn't need the extra info then in the didDeselectAnnotationView: method i hide the table and go back to the full map view, rinse and repeat.. So far so good, everything is working great.
The issue i am having though is that if a user selects another annotation while they currently have an annotation selected then didSelectAnnotationView delegate method gets called BEFORE the didDeselectAnnotationView.
This is obviously a problem because i am using these two methods to decide whether or not i need to display/hide the info table below the mapview, see code below:
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
if ([view.annotation isKindOfClass:[MapLocation class]])
{
if ([self.selectedAnnotation numberOfEvents] == 1)
{
mapTableViewIsVisible = NO;
}
else if ([self.selectedAnnotation numberOfEvents] > 1)
{
// launch mini tableview
mapTableViewIsVisible = YES;
}
[self loadMapTableViewWithEvents:self.selectedAnnotation.events
forAnnotation:self.selectedAnnotation];
}
}
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
if ([view.annotation isKindOfClass:[MapLocation class]])
{
mapTableViewIsVisible = NO;
[self loadMapTableViewWithEvents:nil forAnnotation:(MapLocation*)view.annotation];
}
}
So for example if i select an annotation that needs the maptable and i currently have a regular annotation selected then the mapTable is loaded when the didSelectAnnotationView method above is called, however it is immediately hidden again because the didDeselectAnnotationView is called right after.
So far i havent been able to figure out a way to fix this.
Any ideas??
You could check for the case where no annotations are visible in didDeselectAnnotationView and then clean up your tableview on this case only. As all other cases will be handled by didSelectAnnotation view.
Something like:
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view{
if([[mapView selectedAnnotations] count]==0){
mapTableViewIsVisible = NO;
[self loadMapTableViewWithEvents:nil forAnnotation:(MapLocation*)view.annotation];
}
}