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.
Related
I am a beginner with XCode and I am trying to find a way for the User to input information inside a callbox of a pin they had placed on the map.
So if the User drops a pin and they tap on the pin, I want them to be able to type in a title and a subtitle of that location.
So far, I have created a map using MKMapView and I have implemented UILongPressGestureRecognizer and a void method that fires the moment a pin is created.
I am not sure what to do next? Thank you for your help.
Edit1: I don't have the required reputation to post an image, so here is a link of what I am trying to accomplish: http://imgur.com/gixFxpI
If it is possible to type in the title and subtitle without the use of a disclosure button, that would be swell. Later on I will develop the disclosure button.
Edit2: I have three new questions: 1. Why isn't my disclosure button appearing in my callout? 2. What is reuseidentifier for? Here is what I have so far.
I have embedded a navigation controller to my initial view controller that has the MKMapView in it. I created a second View Controller and I connected the MKMapView to the second View Controller and made my identifier for the second View Controller as 'heylisten' (good old Zelda).
My third question is in the prepareForSegue method, what information needs to go after the dot? destinationViewController.???? = sender.annotation;
// This is your callout box
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"overhere"];
annotationView.canShowCallout = YES;
UIButton *rightDisclosureButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annotationView.rightCalloutAccessoryView = rightDisclosureButton;
return annotationView;
}
// This is a segue when you tap the right disclosure button
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
[self performSegueWithIdentifier:#"heylisten" sender:view];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(MKAnnotationView *)sender
{
if ([segue.identifier isEqualToString:#"heylisten"])
{
ViewController *destinationViewController = segue.destinationViewController;
// grab the annotation from the sender
destinationViewController = sender.annotation;
}
}
If you're targeting iOS 8, use a UIAlertController:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIAlertController_class/
If you're targeting iOS 7 or earlier, use a UIAlertView:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIAlertView_Class/index.html#//apple_ref/occ/cl/UIAlertView
Both of these types have mechanisms to add an input text field and specify a callback to be executed with the text the user typed.
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.
I've read most of the other questions here, as well as read a lot, but I'm not finding an answer.
I'm using this code to create the buttons
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
NSLog(#"called the MKAnnotView method, tag is: %i", self.tag);
static NSString *s = #"ann";
MKAnnotationView *pin = [mapView dequeueReusableAnnotationViewWithIdentifier:s];
if (!pin) {
pin = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:s];
pin.canShowCallout = YES;
pin.calloutOffset = CGPointMake(0, 0);
UIButton *button = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
button.tag=self.tag++;
[button addTarget:self
action:#selector(viewDetails:)
forControlEvents:UIControlEventTouchUpInside];
pin.rightCalloutAccessoryView = button;
}
return pin;
}
-(void) viewDetails: (id) sender {
UIButton *button = sender;
NSLog(#"viewDetails called with button.tag: %i",button.tag);
//[self performSegueWithIdentifier:#"detailView" sender:self];
}
I'm creating a variable amount of pins, in a specific order. When I create them, I get the expected output of "called the MKAnnotView method, tag is 0" then 1, 2, 3, etc.
The annotations are in a very specific order. Zeroth, first, second, so forth. I expect the buttons I created for each annotation to have a tag that fits their index, so that when I segue to the detailViewController, I know which item on the list needs to be pulled and the view populated.
That's not happening. The buttons are each getting randomly assigned tags that repeat. My last case had two tags with 3, and two with zero.
I cannot for the life of me understand why.
Any hints?
Based on comments to my question, the solution I came up with was implementing the following
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
self.tag = [self.annotArray indexOfObject:view.annotation];
NSLog(#"calloutAccessoryControlTapped: annotation = %i", self.tag);
[self performSegueWithIdentifier:#"ShowDetails" sender:self];
}
Whenever I create an annotation, I was already adding it to an annotArray property of this viewController for another use (as the view's built-in annotation array was not populating in a predictable manner)
my prepareForSegue method pulls self.tag and updates a property of the destinationViewController.
I am just starting out wit MKMapKit and call outs. In particular, I have started to use mapView: viewForAnnotation: and a right accessory button. My problem is that the method only get called for newly added pins but not for those previously added to the map view. The call out opens but without a right accessory. Should this method be called for all pins?
-(MKAnnotationView*)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
static NSString *resuseId = #"WaypointMapViewVC";
MKAnnotationView *view =[mapView dequeueReusableAnnotationViewWithIdentifier:resuseId];
if (!view){
view = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:resuseId];
view.canShowCallout=YES;
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
view.rightCalloutAccessoryView=rightButton;
} else {
view.annotation=annotation;
}
return view;
}
Am I doing something wrong here?
I am using the MKMapView object and I am able to create pins and place them on the map. What I am trying to do now is get the information back from the pin. For example in my
- (MKAnnotationView*) mapView:(MKMapView *)mapView viewForAnnotation (id<MKAnnotation>)annotation
I create my pins and set them on the map. I am also creating buttons to use when a user clicks on the pin. All that works well and good. Now my question is when that button is clicked how do I get information from that clicked pin? Below is a small sample code of how I currently have it setup. Any advice would be greatly appreciated.
- (MKAnnotationView*) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
MKPinAnnotationView *annView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"location"];
annView.pinColor = MKPinAnnotationColorRed;
annView.animatesDrop = YES;
annView.canShowCallout = YES;
annView.calloutOffset = CGPointMake(-5, 5);
UIButton* callout = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[callout addTarget:self action:#selector(loadDetails:) forControlEvents:UIControlEventTouchUpInside];
annView.rightCalloutAccessoryView = callout;
return annView;
}
- (void)loadDetails:(id)sender
{
//TODO: Get pin coordinates or address and match it back to an array of available address to show details in a new view
}
Any advice is greatly appreciated
Instead of setting the target of your callout, respond to the delegate method
mapView:annotationView:calloutAccessoryControlTapped:
The annotationView will have an annotation property with the coordinate.
You should create a class that derives from MKPinAnnotationView that has a property of id<MkAnnotationView>. During the method above, create this new object instead of the MKPinAnnotationView and set the id<MKAnnotation> property to the annotation passed in.