I have a map view with pins annotations into it. I need to pass to the detail view the coordinates of a pin when the user press the disclosure button of the pin information. How can I get the coordinates of the pin when I am into the showDetails method? I am using the next code.
- (void)showDetails:(id)sender {
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil ];
// HERE I NEED TO PASS THE COORDINATES OF THE PIN TO THE DETAILVIEWCONTROLLER.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
}
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation {
// If it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
else { // Handles the other annotations.
// Try to dequeue an existing pin view first.
static NSString *AnnotationIdentifier = #"AnnotationIdentifier";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (!pinView) {
// If an existing pin view was not available, creates one.
MKPinAnnotationView *customPinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
customPinView.animatesDrop = YES;
customPinView.canShowCallout = YES;
// Adds a detail disclosure button.
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
customPinView.rightCalloutAccessoryView = rightButton;
return customPinView;
} else
pinView.annotation = annotation;
}
return nil;
}
Thanks for reading.
I cannot give you a working code solution right now since i don't have my mac here. But I can tell you about a possible approach.
Create a method in DetailViewController that populates its attributes, so you can call it from showDetails, before you push it. So the sequence of events would be like this.
Click on disclosure button -> showDetails called -> DetailViewController created and populated -> push DetailViewController
Hope this helped you
You can your UIButton button custom like this :
#interface CustomButton : UIButton {
CLLocationCoordinate2D pinCoordinate;
}
Now in your viewForAnnotation :
// Adds a detail disclosure button.
CustomButton *rightButton = [CustomButton buttonWithType:UIButtonTypeDetailDisclosure];
rightButton.pinCoordinate = annotation.coordinate
[rightButton addTarget:self action:#selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
customPinView.rightCalloutAccessoryView = rightButton;
And finally to get the coordinate in the showDetails method :
CLLocationCoordinate2D currentCoord = ((CustomButton*)sender).pinCoordinate;
Related
I have a code for creating annotation view :
- (MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id<MKAnnotation>)myannotation{
MKAnnotationView *view = nil;
view = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:#"identifier"];
if([myannotation isKindOfClass:[myAnnotation class]]){
if(nil == view) {
view = [[MKPinAnnotationView alloc] initWithAnnotation:myannotation
reuseIdentifier:#"identifier"];
view.canShowCallout = YES;
}
myAnnotation *anns= (myAnnotation*)myannotation;
_annimge=anns.Img;
UIButton *btnViewVenue = [UIButton buttonWithType:UIButtonTypeContactAdd];
[btnViewVenue addTarget:self action:#selector(ButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
btnViewVenue.titleLabel.text=#"GÓWNOKURWA";
view.rightCalloutAccessoryView=btnViewVenue;
}
return view;
}
I would like to show image on button press, thats why I signing image property of annotation to _annimge, but it only shows the last image added, no matter which annotation is active, same thing was happening with ID property which I added, it only returned the highest ID (last added).I am new at iOS and trying to fix this issue for way too long. Thanks for help.
I have simple app with Map and pins attached to it. After clicking on pin on map, pinView is created, on wchich I have button with action called let's say ButtonPressed.
I want to know from which pin it was pressed. I tried something like :
(IBAction)ButtonPressed:(id)sender
{
UIButton *but = (UIButton*) sender;
NSLog(#"SEG PLZ SEG CMON %tu",but.superview.tag);
[self performSegueWithIdentifier:#"segu" sender:sender];
}
But it always returns 0, no matter that I set tag for 5.
Okay I post code for adding buttons as you wanted :
- (MKPinAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)myannotation{
MKPinAnnotationView *view = nil;
//MKPinAnnotationView *view=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"HotSpotsLoc"];
if(myannotation !=mapView.userLocation){
view = (MKPinAnnotationView *)
[mapView dequeueReusableAnnotationViewWithIdentifier:#"identifier"];
if(nil == view) {
view = [[MKPinAnnotationView alloc]
initWithAnnotation:myannotation reuseIdentifier:#"identifier"];
}
UIButton *btnViewVenue = [UIButton buttonWithType:UIButtonTypeContactAdd];
[view.rightCalloutAccessoryView setTag:50];
[btnViewVenue addTarget:self action:#selector(ButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
view.rightCalloutAccessoryView=btnViewVenue;
view.enabled = YES;
view.pinColor = MKPinAnnotationColorPurple;
view.canShowCallout = YES;
view.multipleTouchEnabled = NO;
//view.animatesDrop = YES;
UIButton *btnViewwVenue = [UIButton buttonWithType:UIButtonTypeContactAdd ] ;
[btnViewwVenue addTarget:self action:#selector(addImage:) forControlEvents:UIControlEventTouchUpInside];
[view setTag:50];
view.leftCalloutAccessoryView=btnViewwVenue;
view.enabled = YES;
view.pinColor = MKPinAnnotationColorPurple;
view.canShowCallout = YES;
view.multipleTouchEnabled = NO;
}
return view;
}
Setting leftCalloutAccessoryView and rightCalloutAccessoryView does not necessarily add the views as subviews of view. If you need this relationship to be explicit, consider subclassing UIButton.
#interface MyButton : UIButton
#property (weak) MKPinAnnotationView *annotation;
#end
#implementation MyButton
#end
// Then...
(IBAction)ButtonPressed:(id)sender
{
MyButton *but = (MyButton*) sender;
NSLog(#"SEG PLZ SEG CMON %tu",but.annotation.tag);
[self performSegueWithIdentifier:#"segu" sender:sender];
}
I found out how to push titles and subtitles to DVcontroller but not pictures. I would like to push annotations specific pictures to a new DV when detail disclosure button is tapped. (using Xcode5)
I have the storyboard setup with 2 VC and the first one is embeded in a Nav Controller. The pins show on the map (NSMutable array) and the callout comes up with detail disclosure button on the right (and one on the left as well for future use). The segue from the detail disclosure button works as I can see a blue background screen on the DVcontroller upon tapping it. I have imported pictures files and associated them to each annotation.
I believe the answer is in the "calloutAccessoryControlTapped" method. I tried several codes in that method but still cannot return a picture in the DVcontroller.
ViewController.m is as follows:
(each annotation is set up like this):
//Chateau l'Evesque annotation
myAnn = [[myAnnotation alloc] init];
location.latitude = CLEVESQUE_LATITUDE;
location.longitude = CLEVESQUE_LONGITUDE;
myAnn.coordinate = location;
myAnn.title = #"Château l'Evesque";
myAnn.imageView=[UIImage imageNamed:#"Château l'Evesque"];
[locations addObject:myAnn];
(then viewForAnnotation method):
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:
(id<MKAnnotation>)annotation
{
if([annotation isKindOfClass: [MKUserLocation class]]) return nil;
static NSString *reuseId = #"myAnn";
MKAnnotationView *customAnnotationView = [mapView
dequeueReusableAnnotationViewWithIdentifier:reuseId];
if (customAnnotationView == nil)
{
myAnnotation *myAnn = (myAnnotation *)annotation;
}
MKPinAnnotationView *Mypin=[[MKPinAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:#"current"];
Mypin.pinColor = MKPinAnnotationColorPurple;
UIButton *directionButton = [UIButton buttonWithType:UIButtonTypeCustom];
directionButton.frame = CGRectMake(0, 0, 23, 23);
[directionButton setBackgroundImage:[UIImage imageNamed:#"PetitVolant.png"]
forState:UIControlStateNormal];
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
Mypin.leftCalloutAccessoryView = directionButton;
Mypin.rightCalloutAccessoryView = infoButton;
Mypin.draggable = NO;
Mypin.highlighted = YES;
Mypin.animatesDrop = TRUE;
Mypin.canShowCallout = YES;
return Mypin;
}
(then the culprit):
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control
{
myAnnotation *myAnn = (myAnnotation *)view.annotation;
NSLog(#"myAnn.imageView = %#",myAnn.imageView);
[self performSegueWithIdentifier:#"ShowPhotoSegue" sender:self];
}
(I greened out the "prepareForSegue" method because it is not changing anything to the result so far.)
I rewrote the whole thing. Still the same problem. I am going to try to better explain the issue. I just want to push a picture (.png file) to the next view controller. I only get a blank (white) screen on the Detail VC after tapping the detail disclosure button.
If I include the following prepareForSegue method (as described in the suggested post):
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ToDetail"])
{
MKAnnotationView *annotationView = sender;
[segue.destinationViewController setAnnotation:annotationView.annotation];
I get the following error:
GuideDesVinsCPA[2523:70b] myAnn.imageForMyAnnotation = <UIImage: 0x9a4f510>
GuideDesVinsCPA[2523:70b] -[MapViewController annotation]: unrecognized selector sent to instance 0x9f31970
GuideDesVinsCPA[2523:70b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MapViewController annotation]: unrecognized selector sent to instance 0x9f31970'
I have a map that has multiple annotations that are plotted on the map sourced from JSON data that are broken up by category within a UITableViewController that contains information like their latitude and longitude as well as other information like: address, phone number and so on...
I know how to add a detail disclosure button to the annotation view for each one, but how to do I get that information into a detail viewController?
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if([annotation isKindOfClass:[MKUserLocation class]]) {
return nil;
}
MKPinAnnotationView *pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"annoPin"];
MKAnnotationView *view = [self.mapView dequeueReusableAnnotationViewWithIdentifier:#"annoView"];
if(!view) {
view = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"annoView"];
}
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:nil action:#selector(showDetails :) forControlEvents:UIControlEventTouchUpInside];
pinView.animatesDrop = YES;
view.rightCalloutAccessoryView = rightButton;
view.image = [UIImage imageNamed:#"check.png"];
view.enabled = YES;
view.canShowCallout = YES;
return view;
}
As you can see I've created a button, but how do I get the JSON info for each category over to a detail ViewController for each category inside of the UITableViewController?
When you create the annotation that you add to your mapview you need to give it all the information that will eventually get to the detail view controller, or at least a reference to the data that you can get later. Then in mapView:annotationView:calloutAccessoryControlTapped:, which gets called on the map delegate when a disclosure button is tapped, you get the annotationview's annotation and get the data from there.
I have populated a couple of locations on MKMapView using MKPointAnnotation(s). On tapping annotations I am showing some options with UIActionSheet menu. The options have some delete functionality which would delete the selected annotation on map when user taps the delete option on UIActionSheet. The issue is that I am not able to determine which annotation point is clicked, I seem to have no reference to it.
The code that adds annotation point is:
while(looping array of locations)
{
MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc] init];
annotationPoint.coordinate = {coord of my location}
annotationPoint.title = [anObject objectForKey:#"castTitle"];
annotationPoint.subtitle = [anObject objectForKey:#"storeName"];
[self.mainMapView addAnnotation:annotationPoint];
}
The code to show UIActionSheet on tapping annotation is:
-(MKAnnotationView*)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
if([annotation isKindOfClass:[MKUserLocation class]])
return nil;
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKPinAnnotationView *pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier];
pinView.animatesDrop = YES;
pinView.canShowCallout = YES;
pinView.pinColor = [self getAnnotationColor];
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
[rightButton addTarget:self action:#selector(showOptions:) forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = rightButton;
return pinView;
}
-(IBAction)showOptions:(id)sender
{
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:NSLocalizedString(#"", #"") delegate:self cancelButtonTitle:NSLocalizedString(#"Cancel", #"Cancel") destructiveButtonTitle:nil otherButtonTitles:NSLocalizedString(#"Delete", #"Delete"), nil];
[sheet showInView:[self.view window]];
}
You can also Create a class which inherits from MKPointAnnotation, and add an id property , and use your class :
#interface MyPointAnnotation : MKPointAnnotation
#property int pointId;
#end
and then use it in your view controller:
create annotation:
MyPointAnnotation *myAnnotation = [[MyPointAnnotation alloc]init];
myAnnotation.coordinate= someCoordinates;
[myAnnotation setTitle:#"i am annotation with id"];
myAnnotation.pointId = 1;
[self.mapView addAnnotation:myAnnotation];
if you have an array of coordinates you can loop and create annotations.
and you can even customize annotation view by its id:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
MKPinAnnotationView *view=(MKPinAnnotationView*)[self.mapView dequeueReusableAnnotationViewWithIdentifier:#"reuseme"];
if (!view) {
view=[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:#"reuseme"];
}
if (((MyPointAnnotation *)annotation).pointId == 1)
{
//the annotation with id 1.
}
return view;
}
Seems like there are two approaches.
If only one annotation can be selected at a time, you could access the -selectedAnnotations property of the enclosing MKMapView.
Another approach is to inspect sender in showOptions:, which is a reference to the UIButton that triggered the action. Find out its enclosing MKAnnotationView, which will give you the associated -annotation. You could then either stash this as an ivar or (my preferred approach) use some runtime magic - in the form of objc_setAssociatedObject(), declared in <objc/runtime.h> - to attach a reference to the annotation to the action sheet, allowing easy retrieval in its delegate callback.
(You could actually do this back in the button creation phase if you wanted, and attach a reference to the annotation to the UIButton, which can be picked up directly in showOptions: and reattached to the action sheet.
But [MKMapView selectedAnnotations] I would think is the easier way to go if it suits your needs.