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;
}
Related
I'm a newbie to ios dev. I tried to add pin annotations on map using mapkit. However, after tried the most basic methods, it still didn't show up, either that's a simple pin, or a custom annotationview. There is no error message, it's just the pin won't show up in the map.
Here's my code:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.mapView.delegate = self;
NSLog(#"Custom Annotations start.");
// Custom Annotations.
CLLocationCoordinate2D bryanParkCoordinates = CLLocationCoordinate2DMake(37.785834, -122.406417);
MyCustomAnnotation *bryanParkAnnotation = [[MyCustomAnnotation alloc]initWithTitle:#"Bryant Park" Location:bryanParkCoordinates];
[self.mapView addAnnotation:bryanParkAnnotation];
// Simple pin.
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
[annotation setCoordinate:bryanParkCoordinates];
[annotation setTitle:#"Title"];
[self.mapView addAnnotation:annotation];
// Another try.
CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(37.330713, -121.894348);
MKCoordinateSpan span = MKCoordinateSpanMake(0.1, 0.1);
MKCoordinateRegion region = {coord, span};
MKPointAnnotation *newannotation = [[MKPointAnnotation alloc] init];
[newannotation setCoordinate:coord];
[self.mapView setRegion:region];
[self.mapView addAnnotation:annotation];
// On your location.
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = bryanParkCoordinates;
point.title = #"Where am I?";
point.subtitle = #"I'm here!!!";
[self.mapView addAnnotation:point];
}
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if([annotation isKindOfClass:[MyCustomAnnotation class]])
{
MyCustomAnnotation *myLocation = (MyCustomAnnotation *)annotation;
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:#"MyCustomAnnotation"];
if(annotationView == nil)
annotationView = myLocation.annotationView;
else
annotationView.annotation = annotation;
return annotationView;
}
else{
MKPinAnnotationView *pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"DETAILPIN_ID"];
[pinView setAnimatesDrop:YES];
[pinView setCanShowCallout:NO];
return pinView;
}
}
If I just want a simple pin on map, just adding those lines
// Simple pin.
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
[annotation setCoordinate:bryanParkCoordinates];
[annotation setTitle:#"Title"];
[self.mapView addAnnotation:annotation];
should be enough? Is there other things that I could have missed? Like adding other delegate or something else other than adding those simple codes in 'viewDidLoad'? Thanks so much!
Managing Annotation Views
You should implement this delegate method and create a view for the annotation and return it.
basically when you add an annotation this delegates method will get called and you have to create the view for that annotation within this delegate method
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.mapView.delegate = self;
NSLog(#"Custom Annotations start.");
// Custom Annotations.
CLLocationCoordinate2D bryanParkCoordinates = CLLocationCoordinate2DMake(37.785834, -122.406417);
CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(37.330713, -121.894348);
MKCoordinateSpan span = MKCoordinateSpanMake(0.1, 0.1);
MKCoordinateRegion region = {coord, span};
[self.mapView setRegion:region];
[self.mapView addAnnotation:annotation];
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = bryanParkCoordinates;
point.title = #"Where am I?";
point.subtitle = #"I'm here!!!";
[self.mapView addAnnotation:point];
}
Try the following code:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if (annotation == mapView.userLocation) return nil;
static NSString* Identifier = #"PinAnnotationIdentifier";
MKPinAnnotationView* pinView;
pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:Identifier];
if (pinView == nil) {
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:Identifier];
pinView.canShowCallout = YES;
return pinView;
}
pinView.annotation = annotation;
return pinView;
}
Don't forget to add <MKMapViewDelegate> to your #interface section.
#interface YourViewController () <MKMapViewDelegate>
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
How do I add a button to my placemarks and then get it to push onto a view controller?
- (void)viewDidLoad
{
[super viewDidLoad];
// Set "More" logo in navigation bar
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Navigation"]];
appDelegate=[[UIApplication sharedApplication] delegate];
// Set longatude and latitude to tyne and wear
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(54.995184, -1.566699);
// Set span to cover area
MKCoordinateSpan span = MKCoordinateSpanMake(0.5, 0.5);
// Set region
MKCoordinateRegion regionToDisplay = MKCoordinateRegionMake(center, span);
[self.nearbyMapView setRegion: regionToDisplay];
for (int i = 0; i < [[appDelegate offersFeeds] count]; i++)
{
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
NSString *plotAddress = [[[appDelegate offersFeeds] objectAtIndex:i] valueForKey:#"addressline"];
NSString *plotTitle = [[[appDelegate offersFeeds] objectAtIndex:i] valueForKey:#"title"];
[geocoder geocodeAddressString:plotAddress completionHandler:^(NSArray *placemarks, NSError *error) {
if (placemarks && placemarks.count > 0)
{
CLPlacemark *topResult = [placemarks objectAtIndex:0];
MKPlacemark *placemark = [[MKPlacemark alloc]initWithPlacemark:topResult];
// Set title
MKPointAnnotation *pa = [[MKPointAnnotation alloc] init];
pa.coordinate = placemark.location.coordinate;
pa.title = plotTitle;
// Add placemark to map
[self.nearbyMapView addAnnotation:pa];
}
}];
}
}
I've had a look at MKAnotationView but struggling to understand how to get this working with CLPlacemark.
Add this before you add mapview to self.view
-(void)viewDidLoad
{
MKPointAnnotation *annotation = [[MKPointAnnotation alloc]init];
annotation.coordinate = yourCoordinate;
annotation.title = #"Title";
annotation.subtitle = #"SubTitle";
[mapView1 addAnnotation:annotation];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *pinView = nil;
static NSString *defaultPinID = #"identifier";
pinView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
{
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID];
annotationView.enabled = YES;
pinView.canShowCallout = YES;
UIButton *btn = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
//Accessoryview for the annotation view in ios.
pinView.rightCalloutAccessoryView = btn;
}
else
{
pinView.annotation = annotation;
}
pinView.annotation = annotation;
return pinView;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
//Put your button stuff here...
}
I hope it is useful to you
trying to pass my annotation's data (name, address, phone #, url, description, etc) to a DetailViewController with a table. stuck----please read the code. the data isnt passed with calloutAccessoryTapped. Help?
- (IBAction)gasButton:(id)sender {
[self.mapView removeAnnotations:self.mapView.annotations];
self.localSearchRequest = [[MKLocalSearchRequest alloc] init];
self.localSearchRequest.region = self.mapView.region;
self.localSearchRequest.naturalLanguageQuery = #"gas station";
self.localSearch = [[MKLocalSearch alloc] initWithRequest:self.localSearchRequest];
[self.localSearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
if(error){
NSLog(#"localSearch startWithCompletionHandlerFailed! Error: %#", error);
return;
} else {
for(mapItem in response.mapItems){
MKPointAnnotation *zip = [[MKPointAnnotation alloc] init ];
zip.coordinate = mapItem.placemark.location.coordinate;
zip.title = mapItem.name;
self.mapView.delegate = self;
[self.mapView addAnnotation: zip];
[self.mapView selectAnnotation:zip animated:YES];
[self.mapView setUserTrackingMode:MKUserTrackingModeFollow];
NSLog(#"%# - 1", mapItem.name);
CLLocation *loc1 = [[CLLocation alloc] initWithLatitude:zip.coordinate.latitude longitude:zip.coordinate.longitude];
CLLocation *loc2 = [[CLLocation alloc] initWithLatitude:self.mapView.userLocation.coordinate.latitude longitude:self.mapView.userLocation.coordinate.longitude];
CLLocationDistance distance = [loc1 distanceFromLocation:loc2];
NSString *dist = [[NSString alloc] initWithFormat:#"%.2f miles", distance * 0.000621371192];
zip.subtitle = dist;
}
}
}];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
MKPinAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"MYVC"];
if ([annotation isKindOfClass:[MKUserLocation class]])
{
return nil;
}
else if ([annotation isKindOfClass: [MKPointAnnotation class] ])
{
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annotationView.enabled = YES;
annotationView.animatesDrop = YES;
annotationView.pinColor = MKPinAnnotationColorGreen;
annotationView.canShowCallout = YES;
NSLog(#"%# - 2", mapItem.name);
return annotationView;
}
return nil;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
NSLog(#"%# - tapped", mapItem.name);
//STUCK HERE - mapItem.name is (null)
}
mapItem exists in the for loop of your gasButton function, no where else as far as I can see. You've created an annotation (zip) and added it to your map. In viewForAnnotation you are given that annotation as a parameter and asked to make an annotationView from it. In calloutAccessoryControlTapped you are given an annotationView and told it has been tapped. You need to follow the chain back to your data. From the annotationView get the annotation and from the annotation get your name.
MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
NSLog(#"%# - tapped", view.annotation.title);
}
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;
}