I've been looking around for a solution to the custom callout on MKMapview and I don't want to add images and text to the left or right accessory view. I think I would rather create a UIAlertView that brings up all of the information that map pin that was selected.
I've gathered the lat and long on the map pin from JSON data and that JSON data also contains other info such as: phone number, website link, and so on.
How would I accomplish getting all of that information into a UIAlertView that is called upon pressing the map pin?
Here's some sample code:
self.result = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
if(error == nil)
self.mapLocations = result;
NSLog(#"%#", [result allKeys]);
for (NSDictionary *location in self.mapLocations[#"merchants"]) {
for (NSDictionary *locations in location[#"branches"]) {
NSLog(#"%#",locations);
CLLocationCoordinate2D annotationCoordinate =
CLLocationCoordinate2DMake([locations[#"latitude"] doubleValue],
[locations[#"longitude"] doubleValue]);
Annotation *annotation = [[Annotation alloc] init];
annotation.coordinate = annotationCoordinate;
annotation.title = location[#"name"];
annotation.subtitle = locations[#"street"];
[self.mapView addAnnotation:annotation];
and here is my MKAnnotationView Method:
- (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;
}
Help!
If you want to display the UIAlertView after the disclosure button is pressed you should take out the line about assigning an action to the button and implement – mapView:annotationView:calloutAccessoryControlTapped:. So long as your class is set to be the map's delegate then that function will be called and you can create your UIAlertView from there. On of the parameters to that function is the annotationView from which you can get the MKAnnotation and all the details should be attached to that.
Related
I have a an array of latitude and longitude and using for loop am displaying the MKPointAnnotation on the map. I want to show a view as a popup with data when the specific MKPointAnnotation is tapped.
Here is my code -
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 10000, 10000);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
[_locationManager stopUpdatingLocation];
NSArray *set = [[NSArray alloc] init];
for (int i = 0; i < _json.count; i++) {
_name = [_json[i] valueForKey:#"name"];
_class = [_json[i] valueForKey:#"class"];
set = [_json[i] valueForKey:#"set"];
if (setFreeHour.count != 0) {
for (int j=0;j<set.count;j++) {
NSDictionary *dict = [[NSDictionary alloc] init];
dict = set[j];
_lat = dict[#"latitude"];
_longi = dict[#"longitude"];
CLLocationCoordinate2D coordinate;
coordinate.latitude = [_lat doubleValue];
coordinate.longitude = [_longi doubleValue];
// Add an annotation
MKPointAnnotation *point1 = [[MKPointAnnotation alloc] init];
point1.coordinate = CLLocationCoordinate2DMake(coordinate.latitude, coordinate.longitude);
point1.title = _name;
point1.subtitle = _class;
[self.mapView addAnnotation:point1];
}
}
}
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
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 = [UIImage imageNamed:#"annotation"];
pinView.calloutOffset = CGPointMake(0, 0);
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showDetails)];
[pinView addGestureRecognizer:tap];
} else {
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
- (void)showDetails{
self.popup.hidden = NO;
}
//PS: popup is a view that contains labels. I want to pass data from MKPointAnnotation to the view
Why don't you use mapView(_:didSelect:) method instead of UITapGestureRecognizer?
(void)mapView:(MKMapView *)mapview didSelectAnnotationView:(MKAnnotationView *)view {
// 1. get data from view(MKAnnotationView)
// 2. pass data to another view
}
https://developer.apple.com/documentation/mapkit/mkmapviewdelegate/1452393-mapview
Annotation pin title shows same title for all pins. I have set label to show the title of each pin but I am getting same title for all labels. I did NSLog
of lbl.text and in NSLog it shows different title.
Why am I getting same title for all map pins.
-(void)maprequests
{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// getting an NSString
NSString *emailid = [prefs stringForKey:#"email"];
NSString *deviceid = [Request UDID];
//NSString * walkGUID=[prefs stringForKey:#"walkguid"];
//NSLog(#"walkGUID:%#",walkGUID);
NSString * walkguid=[prefs stringForKey:#"walkguid"];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"http://10.0.0.28/web/ws/get_poilist_walks.php?strEmailID=%#&strDeviceID=%#&strWalkGuid=%#",emailid,deviceid,walkguid]];
NSLog(#"%#",url);
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//AFNetworking asynchronous url request
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
operation.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
self.pointofintrests = [responseObject objectForKey:#"PointOfIntrests"];
NSIndexPath *indexpath;
NSDictionary *tempDictionary= [self.pointofintrests objectAtIndex:indexpath.row];
for (NSDictionary *dictionary in _pointofintrests)
{
MKCoordinateRegion region = { {0.0, 0.0 }, { 0.0, 0.0 } };
NSString * latitude= [dictionary objectForKey:#"Latitude"];
NSString * longitude =[dictionary objectForKey:#"Longitude"];
double strlatitude = [latitude doubleValue];
double strlongitude = [longitude doubleValue];
region.center.latitude =strlatitude;
region.center.longitude = strlongitude;
region.span.longitudeDelta = 0.01f;
region.span.latitudeDelta = 0.01f;
[_mapview setRegion:region animated:YES];
[_mapview setDelegate:self];
DisplayMap *ann = [[DisplayMap alloc] init];
ann.coordinate = region.center;
[_mapview addAnnotation:ann];
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Request Failed: %#, %#", error, error.userInfo);
}];
[operation start];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
MKPinAnnotationView *pinView = nil;
UILabel *label;
if(annotation != mapView.userLocation)
{
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil ) pinView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID];
if(![annotation isKindOfClass:[DisplayMap class]])
return nil;
DisplayMap *a = (DisplayMap *)annotation;
pinView.image=[UIImage imageNamed:#"push_pin#2x"];
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, 30, 250, 30)];
lbl.backgroundColor = [UIColor clearColor];
lbl.textColor = [UIColor whiteColor];
lbl.alpha = 0.5;
lbl.tag = 42;
for (int i=0; i<_pointofintrests.count; i++)
{
lbl.text = [[_pointofintrests valueForKey:#"title"] objectAtIndex:i];
}
[pinView addSubview:lbl];
[_mapview selectAnnotation:pinView animated:YES];
pinView.canShowCallout = YES;
pinView.animatesDrop = NO;
}
else
{
}
return pinView;
}
Your problem is you are looping over _pointofinterests
for (int i=0; i<_pointofintrests.count; i++)
{
lbl.text = [[_pointofintrests valueForKey:#"title"] objectAtIndex:i];
}
This isn't doing what you think. Its assigning the last title in the array to every pin.
Because the viewForAnnotation delegate method gives you the annotation that will display, I tend to keep an array of annotations to save the index, and therefore you can access your data correctly.
When you call [_mapview addAnnotation:ann]; also save ann into an array.
You should then be able todo something like:
[[_pointofintrests valueForKey:#"title"] objectAtIndex:[annArray indexOfObject:annotation]]
As a side note, if _pointofinterests is an NSDictionary I would use objectForKey instead.
The main reason you are getting the same label text on all pins is, as already pointed out in another answer, that for every pin, lbl.text is always set to the title of the last object in _pointofintrests.
The solution I would prefer however is to set the annotation's title and use that to set the label's text.
When creating the annotation and before calling addAnnotation, set its title property:
DisplayMap *ann = [[DisplayMap alloc] init];
ann.coordinate = region.center;
ann.title = [dictionary objectForKey:#"title"]; //<-- add this line
[_mapview addAnnotation:ann];
In viewForAnnotation, instead of the for loop, you can simply set the label's text to the annotation's title (no searching of arrays or looping):
//for (int i=0; i<_pointofintrests.count; i++)
//{
// lbl.text = [[_pointofintrests valueForKey:#"title"] objectAtIndex:i];
//}
lbl.text = annotation.title;
That technically fixes the problem of the same text appearing on all pins.
However, there are some other issues with the code in viewForAnnotation which will become apparent after the above fix:
The UILabel is being added to the annotation view even if the annotation view was dequeued (meaning a previously created view is being re-used). That dequeued view will already have a UILabel in it and the existing code will add another one on top. After panning and zooming the map for a while, you will notice overlapping labels for each pin.
The UILabel should only be added when a new view is created (when the dequeue returns nil and you alloc+init a new one).
Another problem is that since you are using a custom image for your annotations, you should create a plain MKAnnotationView instead of an MKPinAnnotationView. The MKPinAnnotationView class is designed for showing the standard, built-in pin image and although it still has an image property, it tends to sometimes ignore that and revert to showing its standard pin image.
Another problem is this line:
[_mapview selectAnnotation:pinView animated:YES];
The map view can only have one annotation "selected" at a time so if you were thinking that calling this in viewForAnnotation would show the callout for all the annotations at once, then that is mistaken.
The selectAnnotation method requires the annotation as the first parameter. The pinView is not the annotation -- it is the annotation's view (they are not the same thing). The compiler must be complaining about this line and at run-time, the system is probably showing an error in the console saying something like "Trying to select an annotation which has not been added". So technically, the line should be [_mapview selectAnnotation:annotation animated:YES];
Regardless, do not call selectAnnotation in the viewForAnnotation delegate method. Doing so may lead to recursion and a stack overflow (and an EXC_BAD_ACCESS) because the select causes the annotation's view to be updated which causes viewForAnnotation to be called, etc. Instead, call it in the didAddAnnotationViews delegate method for the one annotation you want to show the callout for.
Your revised viewForAnnotation delegate method might look like this:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if(! [annotation isKindOfClass:[DisplayMap class]])
{
return nil;
}
static NSString *defaultPinID = #"MyPin";
int lblTag = 42;
MKAnnotationView *pinView = [mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if (pinView == nil)
{
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID];
pinView.image = [UIImage imageNamed:#"push_pin#2x"];
pinView.canShowCallout = YES;
//Create and add the label to the view ONCE when creating the view...
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, 30, 250, 30)];
lbl.backgroundColor = [UIColor clearColor];
lbl.textColor = [UIColor whiteColor];
lbl.alpha = 0.5;
lbl.tag = lblTag;
[pinView addSubview:lbl];
}
else
{
//If we are re-using a dequeued view
//update its annotation reference...
//(otherwise view will still be pointing to its previous annotation)
pinView.annotation = annotation;
}
//At this point, we have a new or dequeued view
//pointing to the current annotation.
//Now update the label that will already be there
//with the current annotation's title...
UILabel *lbl = (UILabel *)[pinView viewWithTag:lblTag];
lbl.text = annotation.title;
return pinView;
}
Remember you'll need to set the annotation's title as shown at the top of the answer as well.
There are also some things in the for loop in the maprequests method that I want to point out:
It's not necessary to create and set a region just to set the annotation's coordinate. Calling setRegion in the loop is pointless and inefficient since the user will only end up seeing the map positioned at the last annotation anyway. To set an annotation coordinate, just do:
ann.coordinate = CLLocationCoordinate2DMake(strlatitude, strlongitude);
You can call setRegion (once) after the for loop (or just call [_mapview showAnnotations:_mapview.annotations animated:YES]; so you don't have to yourself calculate the region that shows all the annotations).
You don't need to set the map view's delegate inside the for loop repeatedly. Set the delegate (once) before the for loop (though it should already have been set long before this method is called).
I'm making an app with multiple annotations on a mapview. I succeeded in displaying the annotations on the mapview.
I want to use the app to find different stores in one country. So I have all the coordinates and I want that when an annotation is clicked, the Maps app gets launched and the user can get a route from his current location.
My problem is that when I use the calloutAccessoryControlTapped function, every annotation displays the information of the first coordinates I filled in.
This is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
[self plotAnnotations];
}
-(void)plotAnnotations
{
CLLocationCoordinate2D coordinate1;
coordinate1.latitude = 52.511917;
coordinate1.longitude = 4.994776;
MyLocation *annotation = [[MyLocation alloc] initWithCoordinate:coordinate1 title:#"Basic-Fit Purmerend"];
CLLocationCoordinate2D coordinate2;
coordinate2.latitude = 51.972618;
coordinate2.longitude = 5.310799;
MyLocation *annotation2 = [[MyLocation alloc] initWithCoordinate:coordinate2 title:#"Basic-Fit Aalsmeer"];
[self.mapView addAnnotation:annotation];
[self.mapView addAnnotation:annotation2];
}
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
}
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
CLLocationCoordinate2D coordinate1;
coordinate1.latitude = 52.511917;
coordinate1.longitude = 4.994776;
NSDictionary *addressDict1 = #{(NSString*)kABPersonAddressStreetKey:#"Grotenhuysweg 100, 1447 Purmerend, Nederland"};
MKPlacemark *placeMark1 = [[MKPlacemark alloc]initWithCoordinate:coordinate1 addressDictionary:addressDict1];
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placeMark1];
[mapItem setName:#"Basic-Fit Purmerend"];
[mapItem setUrl:[NSURL URLWithString:#"http://www.basic-fit.nl/sportschool/Purmerend"]];
CLLocationCoordinate2D coordinate2;
coordinate2.latitude = 51.972618;
coordinate2.longitude = 5.310799;
NSDictionary *addressDict2 = #{(NSString*)kABPersonAddressStreetKey:#"Molenvliet 18A, Aalsmeer, Nederland"};
MKPlacemark *placeMark2 = [[MKPlacemark alloc]initWithCoordinate:coordinate2 addressDictionary:addressDict2];
MKMapItem *mapItem2 = [[MKMapItem alloc] initWithPlacemark:placeMark2];
[mapItem2 setName:#"Basic-Fit Aalsmeer"];
[mapItem2 setUrl:[NSURL URLWithString:#"http://www.basic-fit.nl/sportschool/aalsmeer"]];
NSArray *mapPoints = #[mapItem];
[MKMapItem openMapsWithItems:mapPoints launchOptions:nil];
NSArray *mapPoints1 =#[mapItem2];
[MKMapItem openMapsWithItems:mapPoints1 launchOptions:nil];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
static NSString *identifier = #"MyLocation";
MKPinAnnotationView *annotationView = (MKPinAnnotationView *) [self.mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (!annotationView)
{
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.image = [UIImage imageNamed:#"arrest.png"];//here we use a nice image instead of the default pins
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
} else {
annotationView.annotation = annotation;
}
return annotationView;
}
I eventually want to display more than 2 annotations on the map. But when I select an annotation, the data provided by coordinate1 are displayed.
How can I solve this?
Nice work so far. The problem is in the -mapView:annotationView:calloutAccessoryControlTapped: delegate method. This method is called when an annotation on the map view is tapped. You're trying to configure and open the Maps app for both of your example annotations in this delegate method which you shouldn't be doing. You should be opening the Maps app using the annotation view that you're given access to. The reason why the first annotation's details are being shown no matter what is because
NSArray *mapPoints = #[mapItem];
[MKMapItem openMapsWithItems:mapPoints launchOptions:nil];
will get called first any time you tap on an annotation.
Here's some stuff that I suggest you do.
You should modify your MyLocation class to have a NSDictionary property that will hold the address and a NSURL property to hold your URL.
So your -plotAnnotations method would look like this now:
-(void)plotAnnotations
{
CLLocationCoordinate2D coordinate1;
coordinate1.latitude = 52.511917;
coordinate1.longitude = 4.994776;
MyLocation *annotation = [[MyLocation alloc] initWithCoordinate:coordinate1 title:#"Basic-Fit Purmerend"];
// Set the address for this annotation
annotation.address = #{(NSString*)kABPersonAddressStreetKey:#"Grotenhuysweg 100, 1447 Purmerend, Nederland"};
annotation.url = [NSURL URLWithString:#"http://www.basic-fit.nl/sportschool/Purmerend"];
CLLocationCoordinate2D coordinate2;
coordinate2.latitude = 51.972618;
coordinate2.longitude = 5.310799;
MyLocation *annotation2 = [[MyLocation alloc] initWithCoordinate:coordinate2 title:#"Basic-Fit Aalsmeer"];
// Set the address for this annotation
annotation2.address = #{(NSString*)kABPersonAddressStreetKey:#"Molenvliet 18A, Aalsmeer, Nederland"};
annotation.url = [NSURL URLWithString:#"http://www.basic-fit.nl/sportschool/aalsmeer"];
[self.mapView addAnnotation:annotation];
[self.mapView addAnnotation:annotation2];
}
Now your -mapView:annotationView:calloutAccessoryControlTapped: delegate method will look like this:
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
// You can retrieve your annotation using the annotation property of MKAnnotationView
MyLocation *annotation = (MyLocation *)view.annotation;
// Then you configure everything like you were doing
MKPlacemark *placeMark = [[MKPlacemark alloc] initWithCoordinate:annotation.coordinate addressDictionary:annotation.address];
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placeMark];
[mapItem setName:annotation.title];
[mapItem setUrl:annotation.url];
[MKMapItem openMapsWithItems:#[mapItem] launchOptions:nil];
}
Something better to do would be to create a class called Place that has properties that stores all of your data pieces. Then you would modify your MyLocation class to initialize with your Place class. Then you would just access your Place class every time you have access to an annotation.
I have a mkmapview that I'm dropping several placemark pins on, however I've not been able to get the pins to show the correct title on the callouts, seems to randomly show a title from the collection of pins on the map. Any ideas? Code looks like:
(void)viewDidLoad {
[super viewDidLoad];
[mapView setDelegate:self];
CLLocationCoordinate2D geos = CLLocationCoordinate2DMake([putInLat doubleValue], [putInLong doubleValue]);
aMarker = [[RNPlaceMark alloc] initWithCoordinate:geos Title:#"Location A"];
CLLocationCoordinate2D geos2 = CLLocationCoordinate2DMake([takeOutLat doubleValue], [takeOutLong doubleValue]);
bMarker = [[RNPlaceMark alloc] initWithCoordinate:geos2 Title:#"Location B"];
NSArray *annots = [[NSArray alloc] initWithObjects:putInMarker, takeOutMarker, nil];
[mapView addAnnotations:annots];
}
and
(MKAnnotationView *)mapView:(MKMapView *)aMapView viewForAnnotation:(id<MKAnnotation>)annotation {
NSString *title = annotation.title;
MKPinAnnotationView *pinView=(MKPinAnnotationView *)[aMapView dequeueReusableAnnotationViewWithIdentifier:title];
if(pinView==nil)
pinView=[[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:title] autorelease];
if(annotation == aMarker)
[pinView setPinColor:MKPinAnnotationColorGreen];
else if(annotation == bMarker)
[pinView setPinColor:MKPinAnnotationColorRed];
pinView.canShowCallout=YES;
pinView.animatesDrop=YES;
return pinView;
}
I switched the code to use MKPointAnnotation it worked fine, so now it looks like...
I'm executing the following code in my viewDidLoad method on the view that host the UIMapVIew:
MKPointAnnotation *myMarker = [[MKPointAnnotation alloc] init];
[myMarker setTitle:#"Hello World"];
CLLocationCoordinate2D geos = CLLocationCoordinate2DMake([myMarkerLat doubleValue], [myMarkerLong doubleValue]);
[myMarker setCoordinate:geos];
NSArray *annots = [[NSArray alloc] initWithObjects:myMarker, nil];
[mapView addAnnotations:annots];
then I have...
- (MKAnnotationView *)mapView:(MKMapView *)aMapView viewForAnnotation:(id
<MKAnnotation>)annotation
{
NSString *title = annotation.title;
MKPinAnnotationView *pinView=(MKPinAnnotationView *)[aMapView dequeueReusableAnnotationViewWithIdentifier:title];
if(pinView==nil)
pinView=[[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:title] autorelease];
//If you want to change the color of the pin you can with something like...
//if(annotation == whatEverInstanceOfAMarkerIWantToKeep)
// [pinView setPinColor:MKPinAnnotationColorGreen];
pinView.canShowCallout=YES;
pinView.animatesDrop=YES;
return pinView;
}
How do I show images instead of pins in the map. So far I can only add pins on tap. A sample code of the .m would extremely help since i'm still new to iOS programming.
#pragma mark -
#pragma mark MKMapView delegate
- (MKAnnotationView *)mapView:(MKMapView *)mapview viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if(annotationView)
return annotationView;
else
{
MKAnnotationView *annotationView = [[[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:AnnotationIdentifier] autorelease];
annotationView.canShowCallout = YES;
annotationView.image = [UIImage imageNamed:#"someImage.png"];
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(writeSomething:) forControlEvents:UIControlEventTouchUpInside];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
annotationView.rightCalloutAccessoryView = rightButton;
annotationView.canShowCallout = YES;
annotationView.draggable = YES;
return annotationView;
}
return nil;
}
EDIT:
I could explain to you all about the MKAnnotationView, but I think you will find the documentation provided by Apple to be a far better explanation than from any other source. Check the overview section in the link.
https://developer.apple.com/documentation/mapkit/mkannotationview
Go to organizer of Xcode and then go to documentation and search weatherMap it shows example for map with including images at annotation.
#pragma mark -
#pragma mark MKMapView delegate
-(void)addAllPinsOnMapView
{
MKCoordinateRegion region = mapViewOffer.region;
region.center = CLLocationCoordinate2DMake(12.9752297537231, 80.2313079833984);
region.span.longitudeDelta= 0.1f;
region.span.latitudeDelta= 0.1f;
[mapViewOffer setRegion:region animated:YES];
mapViewOffer.delegate=self;
arrMapPin=[[NSMutableArray alloc] init];
NSArray *name=[[NSArray alloc]initWithObjects:
#"Title1",
#"Title2",
#"Title3", nil];
NSMutableArray *arrCoordinateStr = [[NSMutableArray alloc] initWithCapacity:name.count];
[arrCoordinateStr addObject:#"12.970760345459,80.2190093994141"];
[arrCoordinateStr addObject:#"12.9752297537231,80.2313079833984"];
[arrCoordinateStr addObject:#"12.9788103103638,80.2412414550781"];
for(int i = 0; i < name.count; i++)
{
NSArray *components = [[arrCoordinateStr objectAtIndex:i] componentsSeparatedByString:#","];
double latitude = [components[0] doubleValue];
double longitude = [components[1] doubleValue];
MKPointAnnotation *mapPin = [[MKPointAnnotation alloc] init];
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);
mapPin.title = [name objectAtIndex:i];
mapPin.coordinate = coordinate;
[mapViewOffer addAnnotation:mapPin];
}
}
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:
(MKAnnotationView *)view
{
NSLog(#"%#",view.annotation.title);
NSLog(#"%f",view.annotation.coordinate.latitude);
NSLog(#"%f",view.annotation.coordinate.longitude);
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(calloutTapped:)];
[view addGestureRecognizer:tapGesture];
}
-(void)calloutTapped:(UITapGestureRecognizer *) sender
{
NSLog(#"Callout was tapped");
MKAnnotationView *view = (MKAnnotationView*)sender.view;
id <MKAnnotation> annotation = [view annotation];
if ([annotation isKindOfClass:[MKPointAnnotation class]])
{
//[self performSegueWithIdentifier:#"annotationDetailSegue" sender:annotation];
OfferDetailsViewController *objOfferDetailsViewController = [[OfferDetailsViewController alloc]init];
[self.navigationController pushViewController:objOfferDetailsViewController animated:YES];
}
}
- (MKAnnotationView *)mapView:(MKMapView *)theMapView
viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *pinView = nil;
static NSString *defaultPinID = #"annotationViewID";
pinView = (MKAnnotationView *)[mapViewOffer dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil ){
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID];
}
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"placeholder"];
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[infoButton addTarget:self action:#selector(infoButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = infoButton;
return pinView;
}