This is BridgeAnnotation interface which has delegate of MKAnnotation
#interface BridgeAnnotation : NSObject <MKAnnotation>
{
}
#property(nonatomic,retain) NSString *lat,*lon,*titlevalue,*subtitlevalue;
#property(nonatomic,assign) NSInteger myindex;
#end
I am setting value to myindex variable in my method like as below
BridgeAnnotation *bridgeAnnotation = [[BridgeAnnotation alloc] init];
[bridgeAnnotation setLat:[#"" stringByAppendingFormat:#"%f",theCoordinate.latitude]];
[bridgeAnnotation setLon:[#"" stringByAppendingFormat:#"%f",theCoordinate.longitude]];
[bridgeAnnotation setTitlevalue:[PMLObj ProductTitle]];
[bridgeAnnotation setSubtitlevalue:[[PMLObj ProductPrice] stringByAppendingFormat:#"$"]];
[bridgeAnnotation setMyindex:i];
[self.mapView addAnnotation:bridgeAnnotation];
THis is my overiding method
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
static NSString* BridgeAnnotationIdentifier = #"bridgeAnnotationIdentifier";
MKPinAnnotationView* pinView = (MKPinAnnotationView *)
[mapView dequeueReusableAnnotationViewWithIdentifier:BridgeAnnotationIdentifier];
if (!pinView)
{
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
NSLog(#"---%d",rightButton.tag);
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
customPinView.rightCalloutAccessoryView = rightButton;
return customPinView;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
In above method I want to access myindex of BridgeAnnotation class..
How it possible? OR I have to use other method for that??
Can any one help me?
If you want to capture the annotation on a click then you should use this delegate
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
BridgeAnnotation *annotation = (BridgeAnnotation *)mapView.annotation;
NSInteger *yourIndex = annotation.myindex;
}
Related
i'm working on a custom annotationview that show a image of background, with inside a custom image.
I've based my code from this: Custom MKAnnotationView with frame,icon and image
And my actually code is:
else if ([annotation isKindOfClass:[ImagePin class]]){
static NSString *identifierImage = #"ImagePinLocation";
MKAnnotationView *annotationImageView = (MKAnnotationView *) [self.mapView dequeueReusableAnnotationViewWithIdentifier:identifierImage];
if(annotationImageView){
return annotationImageView;
}
else {
annotationImageView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifierImage];
annotationImageView.canShowCallout = YES;
annotationImageView.image = [UIImage imageNamed:#"image_bg_mappa"];
UIImage *frame = [UIImage imageNamed:#"image_bg_mappa"];
ImagePin *imagePinImage = annotation;
NSLog(#"%#", [NSString stringWithFormat:#"%#", imagePinImage.image]);
NSString *urlStringForImage = [NSString stringWithFormat:#"%#", imagePinImage.image];
NSURL *urlForImage = [NSURL URLWithString:urlStringForImage];
UIImageView *imageView = [[UIImageView alloc] init];
[imageView setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#", urlForImage]] placeholderImage:[UIImage imageNamed:#"avatar-placeholder.png"]];
UIGraphicsBeginImageContext(CGSizeMake(annotationImageView.image.size.width, annotationImageView.image.size.height));
[frame drawInRect:CGRectMake(0, 0, frame.size.width, frame.size.height)];
[imageView.image drawInRect:CGRectMake(2, 2, 48, 38)]; // the frame your inner image
annotationImageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(writeSomething:) forControlEvents:UIControlEventTouchUpInside];
[rightButton setTitle:#"" forState:UIControlStateNormal];
annotationImageView.canShowCallout = YES;
annotationImageView.rightCalloutAccessoryView = rightButton;
annotationImageView.enabled = YES;
return annotationImageView;
}
}
And then i have two method:
(void)writeSomething {
}
(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
}
But:
Not show my rightButton callout(not show also the button)
I prefer that when i click on the full image/annotation it call mapView annotationView method.
How i can do it ? Why when i click on annotation, it not call my calloutAccessoryControlTapped method ?
In this map i have also more different type of pin(mkpinannotation), and works fine(also the method calloutAccessoryControlTapped works fine with these pins).
Where is the problem ?
Thanks to all, and sorry for my bad english(I'm learning it).
EDIT: My full code for viewForAnnotation method: https://gist.github.com/anonymous/6224519e308d6bf56c4c
The MKPinAnnotation works fine.
EDIT:
This is my ImagePin.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface ImagePin : NSObject <MKAnnotation>
- (id)initWithImage:(NSString*)image imagebeachId:(NSString*)imagebeachId coordinate:(CLLocationCoordinate2D)coordinate;
//- (MKMapItem*)mapItem;
#property (nonatomic, copy) NSString *imagebeachId;
#property (nonatomic, copy) NSString *image;
#property (nonatomic, assign) CLLocationCoordinate2D theCoordinate;
#end
And my ImagePin.m
#import "ImagePin.h"
#import <AddressBook/AddressBook.h>
#interface ImagePin ()
#end
#implementation ImagePin
#synthesize image = _image;
#synthesize imagebeachId = _imagebeachId;
#synthesize theCoordinate = _theCoordinate;
- (id)initWithImage:(NSString*)image imagebeachId:(NSString*)imagebeachId coordinate:(CLLocationCoordinate2D)coordinate {
if ((self = [super init])) {
//self.address = address;
self.image = image;
self.imagebeachId = imagebeachId;
self.theCoordinate = coordinate;
}
return self;
}
- (NSString *)title {
return #"";
}
- (NSString *)subtitle {
return _image;
}
- (CLLocationCoordinate2D)coordinate {
return _theCoordinate;
}
#end
EDIT:
This is where i add annotation:
- (void)imagePositions:(NSDictionary *)responseData {
for (id<MKAnnotation> annotation in self.mapView.annotations) {
if ([annotation isKindOfClass:[ImagePin class]]){
//[self.mapView removeAnnotation:annotation];
}
}
for (NSArray *row in responseData) {
NSString * imageBeachId = [row valueForKey:#"id"];
NSNumber * latitude = [row valueForKey:#"lat"];
NSNumber * longitude = [row valueForKey:#"lng"];
NSString * imageBeach = [row valueForKey:#"fb_photo_url"];
CLLocationCoordinate2D coordinate;
coordinate.latitude = latitude.doubleValue;
coordinate.longitude = longitude.doubleValue;
ImagePin *annotation = [[ImagePin alloc] initWithImage:imageBeach imagebeachId:imageBeachId coordinate:coordinate];
[self.mapView addAnnotation:annotation];
}
}
I have fixed all!
The problem is that title can't be empty(i was using #""... with a #"AAA works fine) and then for not show the callout i have done:
annotationView.canShowCallout = NO;
and implemented:
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
//here you action
}
A BIG thanks to Anna(the solution is your)!
First checkout that you give the delegate to MapView or not , if not then give the delegate like bellow..
yourMapView.delegate = self;
Also in .h file define that delegate like bellow..
#interface ViewController : UIViewController<MKMapViewDelegate,MKAnnotation>{...
after check that this bellow method called when accessory tapped...
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
NSLog(#"Do something ");
}
UPDATE:
Instead of Custom Button try to use it...
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
NSLog(#"viewForAnnotation...");
static NSString *identifier = #"MyLocation";
if ([annotation isKindOfClass:[ImagePin class]]) {
MKAnnotationView *annotationView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil)
{
annotationView = [[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier] autorelease];
}
if (annotation == mapView.userLocation)
return nil;
annotationView.image = [UIImage imageNamed:#"yourImageName.png"];
annotationView.annotation = annotation;
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annotationView.rightCalloutAccessoryView.tag = 101;
annotationView.canShowCallout = YES;
// annotationView.animatesDrop = YES;
return annotationView;
}
return nil;
}
For anyone else that stumbles upon this post while implementing a custom MKAnnotationView, the problem may also be that you have to explicitly set the frame of your view.
MKMapView MKPointAnnotation tap event not called
I was wondering if there is any way to add a UITextField & a UIButton in MKPinAnnotationView callout bubble and in turn if the user clicked button it will call some method?
you can add your custom view instead of MKAnnotationView with bellow code..
you can simple add any control with addSubview property...
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *customPinView = nil;
if(annotation != mapView.userLocation)
{
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( customPinView == nil )
customPinView = [[MKAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID];
customPinView.canShowCallout = YES;
//customPinView.animatesDrop = YES;
customPinView.image = [UIImage imageNamed:#"yourImageName"];//write your imagename
// and add UIButton with bellow code
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self
action:#selector(ShowStoreDetail:)
forControlEvents:UIControlEventTouchUpInside];
customPinView.rightCalloutAccessoryView = rightButton;here
}
else {
[mapView.userLocation setTitle:#"I am here"];
}
return pinView;
}
i hope it is useful to you...
:)
I'm a noob to iphone developoment and i am trying to determine the int value of an annotation so I can then take that int value and cross reference it to an array to get a corresponding value. However, when i try to get the int value with the .tag method the value always returns as zero. If I have 5 annontations I need to be able to determine which annontation is 0,1,2,3 and 4. Any help is greatly appreciated.
MY CODE
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
if (view.selected==YES) {
NSInteger annotationIndex = view.tag; //Always returns zero
NSLog(#"annotationIndex: %i", annotationIndex);
}
}
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
// Define your reuse identifier.
static NSString *identifier = #"MapPoint";
if ([annotation isKindOfClass:[MapPoint class]]) {
MKPinAnnotationView *annotationView = (MKPinAnnotationView *) [self.mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
} else {
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.animatesDrop = YES;
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
NSInteger clickIndex = rightButton.tag; //Always returns zero, despite there being 5 annotations
NSLog(#"buttonIndex: %i", clickIndex);
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
annotationView.rightCalloutAccessoryView = rightButton;
return annotationView;
}
return nil;
}
The tag property is something you have to set. I think you're not setting it anywhere.
Certainly for the UIButton that you create using buttonWithType. The default tag value is 0, so you're always going to get 0 asking for the tag right after the view (Button) is created.
Write below code to get index value
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
// Annotation is your custom class that holds information about the annotation
if ([view.annotation isKindOfClass:[Annotation class]]) {
Annotation *annot = view.annotation;
NSInteger index = [self.arrayOfAnnotations indexOfObject:annot];
}
}
With my previous post https://stackoverflow.com/a/34742122/3840428
I have a map view and there are 10 store locations which data comes via webservice. I just want to push to my detail view to show address, telephone and other informations of the clicked store.
I need to pass data to my detailview when user tapped or touch up inside to a annotation on mapkit. There are 10 annotations in my mapview and first I want to know, how can I understand or how can I get the annotationID of which annotation is clicked?
this is the method I return pins
- (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=MKPinAnnotationColorPurple;
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = rightButton;
return pinView;
}
/* and my action method for clicked or tapped annotation: */
- (IBAction)showDetails:(id)sender{
NSLog(#"Annotation Click");
[[mtMap selectedAnnotations]objectAtIndex:0];
magazaDetayViewController *detail = [[magazaDetayViewController
alloc]initWithNibName:#"magazaDetayViewController" bundle:nil];
detail.sehir=#"";
detail.magazaAdi=#"";
detail.adres=#"";
detail.telefon=#"";
detail.fax=#"";
[self.navigationController pushViewController:detail animated:YES];
}
if i can just get the clicked annotation index no i can fill detail properties with my array.
if this is impossible is there any other way to do it?
First in your annotaion view delegat make a button to go in detail view like bellow:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
MKPinAnnotationView *mypin = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:#"current"];
mypin.pinColor = MKPinAnnotationColorPurple;
mypin.backgroundColor = [UIColor clearColor];
UIButton *goToDetail = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
mypin.rightCalloutAccessoryView = myBtn;
mypin.draggable = NO;
mypin.highlighted = YES;
mypin.animatesDrop = TRUE;
mypin.canShowCallout = YES;
return mypin;
}
Now use the following delegate whenever the button in annotationView will get tapped the following delegate will be called from where you can easly get which particular annotaion's button is tapped
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control
{
annotation *annView = view.annotation;
detailedViewOfList *detailView = [[detailedViewOfList alloc]init];
detailView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
detailView.address = annView.address;
detailView.phoneNumber = annView.phonenumber;
[self presentModalViewController:detailView animated:YES];
}
here annotaion is a class importing MKAnnotaion.h and address and phonenumber are properties of annotaion class you can make many more while the address and phoneNumber properties of detailView class are strong. So that you can pass values. Hope this will help you!
Bellow is Delegate method of MapView......
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
}
when user tap annotation pin above method call automaticaly if method define in .m file nut first declare MKMapViewDelegate delegate in .h file
and also you can get title or subtitle and id from google place API....
link is...
https://developers.google.com/maps/documentation/places/
for(int i=0; i<[arrLat count];i++) {
CLLocationCoordinate2D theCoordinate1;
konumpin* myAnnotation1=[[konumpin alloc] init];
theCoordinate1.latitude = [[arrLong objectAtIndex:i] doubleValue];
theCoordinate1.longitude = [[arrLat objectAtIndex:i] doubleValue];
myAnnotation1.coordinate=theCoordinate1;
myAnnotation1.title=[arrMagaza objectAtIndex:i];
[annotations addObject:myAnnotation1];
}
[mtMap addAnnotations:annotations];
I have created a MKAnnotationView and do add a UIButton on it. Now I would like that button to remove the pin it is in.
This is how I add the button:
- (MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
MKPinAnnotationView *pinAnnotation = nil;
if(annotation != myMapView.userLocation)
{
NSString *defaultPinID = [[NSString alloc] initWithFormat:#"pin%d",pinCount];
pinAnnotation = (MKPinAnnotationView *)[myMapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinAnnotation == nil )
pinAnnotation = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
pinAnnotation.canShowCallout = YES;
//// ADDING MY BUTTON
UIButton *deleteButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinAnnotation.rightCalloutAccessoryView = deleteButton;
//// ADDING IT'S ACTION
[deleteButton addTarget:self action:#selector(deletePin) forControlEvents:UIControlEventTouchUpInside];
}
pinCount++;
return pinAnnotation;
}
As you can see there, I set the action to call this method:
-(void)deletePin
{
//What to put here...?
}
How can I make that action delete it's button's pin?
I figured maybe sending the id thru or something, but am not sure how.
With annotation callout accessory views, do not use your own target/action method.
Instead, use the map view's calloutAccessoryControlTapped delegate method which will make this job much easier.
Remove the addTarget line and your custom method. Then implement the delegate method instead:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control
{
[mapView removeAnnotation:view.annotation];
}
Also, unrelated, but the way you are setting the re-use identifier is wrong and defeats re-usability by assigning a different id to every annotation. The following is recommended:
- (MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
MKPinAnnotationView *pinAnnotationView = nil;
if (annotation != myMapView.userLocation)
{
NSString *reuseId = #"StandardPin";
pinAnnotationView = (MKPinAnnotationView *)[myMapView dequeueReusableAnnotationViewWithIdentifier:reuseId];
if ( pinAnnotationView == nil )
{
pinAnnotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId] autorelease];
pinAnnotationView.canShowCallout = YES;
UIButton *deleteButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinAnnotationView.rightCalloutAccessoryView = deleteButton;
}
else
//update annotation property if view is being re-used...
pinAnnotationView.annotation = annotation;
}
return pinAnnotationView;
}
Get the sender in your callback
[deleteButton addTarget:self action:#selector(deletePin:) forControlEvents:UIControlEventTouchUpInside];
-(void)deletePin:(id)sender
{
//What to put here...?
}
Then get the MKAnnotation associated with the MKPinAnnotationView, remove it from the MKMapView's annotations and redraw ([mapView setNeedsDisplay])