I subclassed MKPointAnnotation and added a NSString and a UIImage so I can pass these elements to an MKPinAnnotationView. The string passes into the MKPinAnnotationView fine, but the image attribute is coming through as null. I can't figure out why. I will say that one time running this code on my phone the image appeared on a pin once, so maybe I have a memory leak? The other 1000 times I've compiled the images show as null in the log and do not appear. Any help is appreciated.
Here is my subclass customMapAnnotation.h:
#interface customMapAnnotation : MKPointAnnotation
#property (strong, nonatomic) NSString *restaurantID;
#property (strong, nonatomic) UIImage *restaurantIcon;
#end
Here is where my customMapAnnotation is created. I'm using Parse.com so there is a statement here to convert a PFFile to a UIImage. If I check the log I confirm that foodPoint.restaurantIcon has a value when this is ran.
customMapAnnotation *foodPoint = [[customMapAnnotation alloc] init];
foodPoint.coordinate = spot;
foodPoint.restaurantID = [object objectId];
foodPoint.title = [object objectForKey:#"restaurantName"];
foodPoint.subtitle = [object objectForKey:#"cuisineType"];
leftIcon = [object objectForKey:#"restaurantImage"];
[leftIcon getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
image = [UIImage imageWithData:data];
// image can now be set on a UIImageView
foodPoint.restaurantIcon = image;
}
}];
[self.mainMap addAnnotation:foodPoint];
Now here is all of my code for my MKPinAnnotationView. Notice I run an NSLog to confirm if fp.restaurantIcon has a value, and it is null. I know this use of NSLog is not graceful, but it should return the memory location of the image. It comes back null. Again, my other custom attribute fp.restaurantId is working fine.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
static NSString *identifier = #"RoutePinAnnotation";
if (annotation == mapView.userLocation)
{
return nil;
}
else
{
MKPinAnnotationView *pinView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:identifier];
pinView.animatesDrop=NO;
pinView.canShowCallout=YES;
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
//cast annotation parameter to our class so compiler understands...
customMapAnnotation *fp = (customMapAnnotation *)annotation;
NSLog(fp.restaurantIcon);
//get restaurantID from the annotation parameter ("fp")...
[rightButton setTitle:fp.restaurantID forState:UIControlStateNormal];
[rightButton addTarget:self
action:#selector(buttonMethod:)
forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = rightButton;
//NSLog(fp.restaurantIcon);
UIImageView *profileIconView = [[UIImageView alloc] initWithImage:fp.restaurantIcon];
profileIconView.frame = CGRectMake(0,0,31,31);
pinView.leftCalloutAccessoryView = profileIconView;
return pinView;
}
}
Here is my didSelectAnnotationView:
- (void) mainMap:(MKMapView *)mainMap didSelectAnnotationView:(MKAnnotationView *)view
{
if ([view.annotation isKindOfClass:[chwMapAnnotation class]])
{
chwMapAnnotation *fp = (chwMapAnnotation *)view.annotation;
UIImageView *profileIconView = [[UIImageView alloc] initWithImage:fp.restaurantIcon];
profileIconView.frame = CGRectMake(0,0,31,31);
view.leftCalloutAccessoryView = profileIconView;
}
}
I agree with the comment by #Vincent that since the images are being loaded in the background asynchronously, they have not yet been loaded when viewForAnnotation is called and so the annotation's callout is stuck with a blank left icon.
When the image loading is finished by getDataInBackgroundWithBlock, there is no automated signal telling the annotation view to refresh its leftCalloutAccessoryView.
A crude workaround in this case would be to manually force the refresh of the leftCalloutAccessoryView when the annotation is selected (which is when the callout will be displayed containing the leftCalloutAccessoryView).
When an annotation is selected, the map view calls the didSelectAnnotationView delegate method. Here, the crude workaround can be applied:
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
if ([view.annotation isKindOfClass:[customMapAnnotation class]])
{
customMapAnnotation *fp = (customMapAnnotation *)view.annotation;
UIImageView *profileIconView = [[UIImageView alloc] initWithImage:fp.restaurantIcon];
profileIconView.frame = CGRectMake(0,0,31,31);
view.leftCalloutAccessoryView = profileIconView;
}
}
Of course, it's possible that the image still hasn't loaded for the annotation that was selected (it's either just taking very long or the image url is invalid, etc).
What you can do is in viewForAnnotation, if fp.restaurantIcon is nil, set the left icon to some generic "loading" icon that you add to the project resources. In didSelectAnnotationView, you can also first check if fp.restaurantIcon is still nil and, if so, do nothing (ie. leave the icon as the generic "loading" icon).
A less crude solution might be to create a custom annotation view class that listens for an "image finished loading" message from its associated annotation and refreshes itself automatically.
I would say don't try to subclass MKPointAnnotation, create your own object that conforms to the MKAnnotation protocol, and use annotation views that are NOT MKPinAnnotationViews.
Related
I have an array of images, that are associated with each Annotation on my map. I can statically add an image to the leftCalloutAccessoryView but I am unsure how to make this dynamic. I hope its clear what I am asking. Each annotation has its own individual image that I want to display but I am unsure of how to reference the image in the following method;
- (MKAnnotationView *)mapView:(MKMapView *)mv viewForAnnotation:(id <MKAnnotation>)annotation
{
if([annotation isKindOfClass:[MKUserLocation class]])
return nil;
NSString *annotationIdentifier = #"PinViewAnnotation";
MyAnnotationView *pinView = (MyAnnotationView *) [mv dequeueReusableAnnotationViewWithIdentifier:annotationIdentifier];
if (!pinView)
{
pinView = [[MyAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annotationIdentifier];
pinView.canShowCallout = YES;
UIImageView *houseIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Icon"]];//static image
[houseIconView setFrame:CGRectMake(0, 0, 30, 30)];
pinView.leftCalloutAccessoryView = houseIconView;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
My array "self.sandwiches" contains Sandwich objects that have a name (NSString) and an imageName ('NSString').
Im looking for a solution where I can get the index of the pin that is selected, similar to a UITableView where you can get its index, and access it from the array using indexPath.row.
My Annotation class;
.h
#import
#import
#import
#interface SandwichAnnotation : NSObject<MKAnnotation>
#property (nonatomic,assign) CLLocationCoordinate2D coordinate;
#property (nonatomic,copy) NSString * title;
#property (nonatomic,copy) NSString * subtitle;
#end
.m
#import "SandwichAnnotation.h"
#implementation SandwichAnnotation
#synthesize coordinate,title,subtitle;
#end
In viewForAnnotation, rather than "getting the index of the pin" (which would work but is less efficient here than with a UITableView), I suggest adding the data required to the annotation class itself.
This way, the data is more self-contained and the code in the delegate method or elsewhere doesn't need to worry, know, or be kept in sync with where or what kind of structure the annotation object is stored in. As long as you have a reference to the annotation object, you will immediately have all the data needed for that annotation (or at least it will contain references to the related data within itself).
The viewForAnnotation delegate method provides a reference to the annotation object it needs a view for (the annotation parameter). It's typed generically as id<MKAnnotation> but it is actually an instance of the exact type that was created (either SandwichAnnotation by you or MKUserLocation by the map view).
One option is to make the parent Sandwich class itself implement MKAnnotation and eliminate the SandwichAnnotation class. This way, no searching or references are needed at all since the annotation parameter will actually be a Sandwich.
However, you may want to keep a separate class for your annotation objects (which is fine). In this case, you can add a reference to the parent object(s) in the annotation class. Example:
#interface SandwichAnnotation : NSObject<MKAnnotation>
#property (nonatomic,assign) CLLocationCoordinate2D coordinate;
#property (nonatomic,copy) NSString * title;
#property (nonatomic,copy) NSString * subtitle;
#property (nonatomic,retain) Sandwich * whichSandwich; // <-- add reference
#end
When creating a SandwichAnnotation, set the reference to which Sandwich the annotation is for:
for (Sandwich *currentSandwich in self.sandwiches) {
SandwichAnnotation *sa = [[SandwichAnnotation alloc] init...];
sa.coordinate = ...
sa.title = ...
sa.whichSandwich = currentSandwich; // <-- set reference
[mapView addAnnotation:sa];
}
Finally, in viewForAnnotation, if annotation is of type SandwichAnnotation, set the leftCalloutAccessoryView:
- (MKAnnotationView *)mapView:(MKMapView *)mv viewForAnnotation:(id <MKAnnotation>)annotation
{
if (! [annotation isKindOfClass:[SandwichAnnotation class]]) {
//If annotation is not a SandwichAnnotation, return default view...
//This includes MKUserLocation.
return nil;
}
//At this point, we know annotation is of type SandwichAnnotation.
//Cast it to that type so we can get at the custom properties.
SandwichAnnotation *sa = (SandwichAnnotation *)annotation;
NSString *annotationIdentifier = #"PinViewAnnotation";
MyAnnotationView *pinView = (MyAnnotationView *) [mv dequeueReusableAnnotationViewWithIdentifier:annotationIdentifier];
if (!pinView)
{
pinView = [[MyAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annotationIdentifier];
pinView.canShowCallout = YES;
//Here, just initialize a blank UIImageView ready to use.
//Set image below AFTER we have a dequeued or new view ready.
UIImageView *houseIconView = [[UIImageView alloc] init];
[houseIconView setFrame:CGRectMake(0, 0, 30, 30)];
pinView.leftCalloutAccessoryView = houseIconView;
}
else
{
pinView.annotation = annotation;
}
//At this point, we have a dequeued or new view ready to use
//and pointing to the correct annotation.
//Update image on the leftCalloutAccessoryView here
//(not just when creating the view otherwise an annotation
//that gets a dequeued view will show an image of another annotation).
UIImageView *houseIconView = (UIImageView *)pinView.leftCalloutAccessoryView;
NSString *saImageName = sa.whichSandwich.imageName;
UIImage *houseIcon = [UIImage imageNamed: saImageName];
if (houseIcon == nil) {
//In case the image was not found,
//set houseIcon to some default image.
houseIcon = someDefaultImage;
}
houseIconView.image = houseIcon;
return pinView;
}
This may sound like a generic question but I've only found answers if I want the same image for all my pins, which i don't.
That's how i'm working right now :
I have all my locations in an array of Locations (custom class with long, lat, name, pin name).
in the viewdidLoad I loop that array and create my pins with every object found, see following code :
for(int i = 0 ; i<[_locationList count] ; i++)
{
Location *item = [_locationList objectAtIndex:i];
CLLocationCoordinate2D coordinate;
coordinate.latitude = item.locationLatitude;
coordinate.longitude = item.locationLongitude;
NSString *title = item.locationName;
CustomAnnotation* ann = [CustomAnnotation new];
ann.name = title;
ann.coordinate = coordinate;
ann.pinName = [NSString stringWithFormat:#"pin%i.png",item.idPin];
[self.map addAnnotation:ann];
}
This is pretty straight forward, part from the CustomAnnotation class, which is the following code :
#interface CustomAnnotation : MKPointAnnotation <MKAnnotation>{
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSString *description;
#property (nonatomic, retain) NSString *pinName;
#end
This is all from stuff i've seen around the internet, and I kinda believe it's all correct up to that point.
In my mind, i'm still creating very classic pins, they just have one more property (pinName), which is why it's coming from the custom class.
Now, in the viewForAnnotation, i have absolutly NO IDEA how to tell it to get that pinName and use it.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
// If it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// Handle any custom annotations.
if ([annotation isKindOfClass:[MKPointAnnotation class]])
{
// Try to dequeue an existing pin view first.
MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if (!pinView)
{
// If an existing pin view was not available, create one.
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.image = // I wanted to write annotation.pinName But it's just not that.
pinView.calloutOffset = CGPointMake(0, 32);
}else {
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
What am I missing? I'm obviously doing something wrong but i jsut can't figure it out, and i'm still quite confused with the differences between MKAnnotationsView & MKPointAnnotation & MKPinAnnotation, ...
More info : the pin names are " pinX.png ", X being a number between 1 and 12. I just want to use that name so the program can find it in the ressources where the picture lies.
Since your annotations are of type CustomAnnotation, it would be more accurate to check if the annotations are of that kind instead of MKPointAnnotation.
Then, casting the annotation parameter to your custom class will let you easily access the custom properties in it like this:
CustomAnnotation *ca = (CustomAnnotation *)annotation;
pinView.image = [UIImage imageNamed:ca.pinName];
However, because the image can be different for each annotation, you should set it after the annotation view has been created or dequeued (not only in the if (!pinView) block -- otherwise an annotation could end up re-using the view from another annotation no longer visible and the wrong image will show).
The updated method would look like this:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
// If it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// Handle any custom annotations.
if ([annotation isKindOfClass:[CustomAnnotation class]])
{
// Try to dequeue an existing pin view first.
MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if (!pinView)
{
// If an existing pin view was not available, create one.
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.calloutOffset = CGPointMake(0, 32);
//NOTE:
//If the calloutOffset needs to be different for each image,
//then this line should also be set below with the image.
}
else {
pinView.annotation = annotation;
}
//Set image on view AFTER we have a new or dequeued view
//because image is based on each annotation...
CustomAnnotation *ca = (CustomAnnotation *)annotation;
pinView.image = [UIImage imageNamed:ca.pinName];
//Might want to check that the UIImage is not nil
//in case pinName is invalid since that would result in
//an invisible annotation view. If the UIImage is nil,
//set pinView.image to some default image.
return pinView;
}
return nil;
}
For the confusion about the differences between the MapKit classes, see:
Should I use MKAnnotation, MKAnnotationView or MKPinAnnotation?. Even though that question is tagged MonoTouch, it still applies.
MKMapView, animateDrop? may also help.
I want to show all user photos to map in iOS.Here,all user photos are coming from server through web service.
let me attach screen show what I want to achieve to get better idea.
e.g image of pin:
So I want to create custom pin like above for all users to show in map of iphone application.
can any one redirect me to achieve above task in ios.
Thanks in advance.
I am pasting a code from one of my project. but you will get main idea. i am dealing with bunch or different stores so i add tag on every annotation. also i am using SDWebImage library to load remote images dynamically.
the green pin is mapPin and circle image is dynamically loaded from server
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation {
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
MKAnnotationView *aView = [mapView dequeueReusableAnnotationViewWithIdentifier:#"mapPin"];
if(aView){
aView.annotation = annotation;
} else {
aView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"mapPin"];
ESMapViewAnnotation *newAnnotation=(ESMapViewAnnotation *)annotation;
ZBStore *s=(ZBStore *)[dataArray objectAtIndex:newAnnotation.tag];
NSString *iURL=s.Icon;
UIImageView *imageView = [[UIImageView alloc] init];
[imageView setImageWithURL:[NSURL URLWithString:iURL]
placeholderImage:[UIImage imageNamed:#"Question.jpg"]];
imageView.layer.borderWidth=1;
imageView.layer.borderColor=[[UIColor whiteColor]CGColor];
imageView.backgroundColor=s.BColor;
CGRect f= CGRectMake(2,2,46,43);
[imageView setFrame:f];
imageView.layer.cornerRadius=22.0;
imageView.layer.masksToBounds=YES;
aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[aView addSubview:imageView];
aView.enabled = YES;
aView.canShowCallout = YES;
aView.image = [UIImage imageNamed:#"gPin2.png"];//here we use a nice image instead of the default pins
}
return aView;
//return nil;
}
I have a map view controller (UIViewController, MKMapView), with its delegate (HCIResultMapViewController).
I wish to have following functionality in this part.
1). I wish to use my custom made NSObject , so that I can associate others details along with the basic entities like title, subtitle etc.
Hence according to my needs I coded as following
In HCIResultMapViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_houseList = [[_resultList objectForKey:#"result"] objectForKey:#"listings"];
// NSLog([_houseList description]);
int i = 0;
for (NSDictionary *house in _houseList) {
HCIAnnotationViewController *annotation = [[HCIAnnotationViewController alloc]
initwithHouse:house];
[_mapView addAnnotation:annotation];
// NSLog(#"asdjhasdjsajdhaksdjghasdasdjahsdahskvdka");
self.currIdentifier = i;
i++;
}
[_mapView setShowsUserLocation:NO];
}
The other delegate functions
-(void) mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
for (NSObject<MKAnnotation> *annotation in _mapView.selectedAnnotations) {
NSLog(#"hellomaster");
NSLog(annotation.title);
if ([annotation isKindOfClass:[HCIAnnotationViewController class]]) {
NSLog(#"hellomaster");
}
}
The last one
-(MKAnnotationView*) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
NSString *identifier = #"currIdentifier";
MKPinAnnotationView *annotationView =
(MKPinAnnotationView *)[_mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation
reuseIdentifier:identifier];
} else {
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.tag = self.currIdentifier;
// Create a UIButton object to add on the
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
[annotationView setRightCalloutAccessoryView:rightButton];
/*
UIButton *leftButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[leftButton setTitle:annotation.title forState:UIControlStateNormal];
[annotationView setLeftCalloutAccessoryView:leftButton];
*/
return annotationView;
}
But I see that the class equivalence fails. Can you tell me what I'm doing wrong?
I think what I want, in simple words, is, how can I send some data (NSDictionary*) along with a annotation such that I can retrieve it whenever I want?
Please dont tag this as repeated question or so. I have tried many questions, googling etc. but couldn't find a suitable solution for this.
Here You can also set NSMutableDictionary instand of NSString.
Create custom AnnotationView:
#import <MapKit/MapKit.h>
#interface AnnotationView : MKPlacemark
#property (nonatomic, readwrite, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, strong) NSString *title; //Here You cam set `NSMutableDictionary` instand of `NSString`
#property (nonatomic, strong) NSString *subtitle; //Here You cam set `NSMutableDictionary` instand of `NSString`
#end
And in .m file
#import "AnnotationView.h"
#implementation AnnotationView
- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate addressDictionary:(NSDictionary *)addressDictionary
{
if ((self = [super initWithCoordinate:coordinate addressDictionary:addressDictionary]))
{
self.coordinate = coordinate;
}
return self;
}
#end
// Use Annotation Add #import "AnnotationView.h" in your relevant .m file:
CLLocationCoordinate2D pCoordinate ;
pCoordinate.latitude = LatValue;
pCoordinate.longitude = LanValue;
// Create Obj Of AnnotationView class
AnnotationView *annotation = [[AnnotationView alloc] initWithCoordinate:pCoordinate addressDictionary:nil] ;
annotation.title = #"I m Here";
annotation.subtitle = #"This is Sub Tiitle";
[self.mapView addAnnotation:annotation];
I couldn't find exact way to implement custom data variables or the reason why my class equivalence fails. But I figured out a way to over come this kind of situation. This might be redundant in method, but still works like a charm.
So the idea is to use the tagging system in control button. I observed that every time I send a message to my map view to add a annotation it immediately calls my viewforannotation method. Since I'm iterating through an array, I maintained a index global pointer, with which I set tag of the control button. Later when the button is clicked, I retrieve the tag and use it to get the object I want.
Anyone else have any alternative or direct solution, please do post.
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.