mapView and UITable detail - uitableview

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);
}

Related

How to add Tap gesture on MKPointAnnotation to show another view with data?

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 access the available data when I click an annotation?

I have several annotation points. What I want to do is when I click an annotation point I want to display that data. I have a custom Annotation class with a title and an NSDictionary. The dictionary contains an image URL and ID. I want to fetch these when I click on a specific annotation.
EDIT: I know about the didSelectAnnotation, but how do I access the data?
-(void)annotations{
CLLocationCoordinate2D pinPoint;
for (NSDictionary * dict in _dataArray) {
pinPoint.latitude =[[dict valueForKey:#"lat"] doubleValue];
pinPoint.longitude = [[dict valueForKey:#"lng"] doubleValue];
_myAnnotation = [[MapViewAnnotation alloc]initWithTitle:[dict valueForKey:#"name"]andCoordinate:pinPoint andData:dict];
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:pinPoint addressDictionary:nil] ;
_destination = [[MKMapItem alloc] initWithPlacemark:placemark];
_myAnnotation.title=[dict valueForKey:#"name"];
[self.mapKit addAnnotation:_myAnnotation];
}
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[self.mapKit setRegion:[self.mapKit regionThatFits:region] animated:YES];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(MapViewAnnotation*)annotation
{
// If it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// Handle any custom annotations.
if ([annotation isKindOfClass:[MapViewAnnotation 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;
NSLog(#"%#",[annotation.data valueForKey:#"name"]);
pinView.image = [UIImage imageNamed:#"image"];
pinView.calloutOffset = CGPointMake(0, 32);
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinView.rightCalloutAccessoryView = rightButton;
} else {
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
[request setTransportType:MKDirectionsTransportTypeWalking];
request.source = [MKMapItem mapItemForCurrentLocation];
request.destination = _destination;
request.requestsAlternateRoutes = NO;
MKDirections *directions =
[[MKDirections alloc] initWithRequest:request];
[directions calculateDirectionsWithCompletionHandler:
^(MKDirectionsResponse *response, NSError *error) {
if (error) {
// Handle Error
} else {
[self showRoute:response];
}
}];
}
EDIT 2nd :
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
MapViewAnnotation * annotation = (MapViewAnnotation *) view;
NSLog(#"%#",[annotation.data valueForKey:#"name"]);
NSURL *url =[NSURL URLWithString:[[NSUserDefaults standardUserDefaults] objectForKey:#"SPOTTD_profilePic"]];
NSData *imageData = [NSData dataWithContentsOfURL:url];
_imgMyProfile.image = [UIImage imageWithData:imageData];
}
You can use the didSelectAnnotationView method, in combination with the annotation property of the MKAnnotationView:
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
if ([view.annotation isKindOfClass:[MapViewAnnotation class]]) {
MapViewAnnotation *annotation = (MapViewAnnotation)view.annotation;
}
}
After you have safely cast the annotation to your custom type, you can access its properties like the NSDictionary.
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
NSString *latPoint2 = [NSString stringWithFormat:#"%.6f", view.annotation.coordinate.latitude];
NSString *longPoint2 =[NSString stringWithFormat:#"%.6f", view.annotation.coordinate.longitude];
There is one more method for annotation which is
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{}.In this method you can show your data on click of annotation.Hope this will help you. If any query let me know. Thanks

Add Pin Color to MKAnnotation

I have a button on Map which directs to "MyLocation" its hardcore lat n lng. i want to change the pin color. Tried some but not successful. Heres the code.
- (IBAction)btnMylLocation:(UIButton *)sender {
CLLocationCoordinate2D coord = {.latitude = 18.520430, .longitude = 73.856744};
MKCoordinateSpan span = {.latitudeDelta = 0.2, .longitudeDelta = 0.2};
MKCoordinateRegion region = {coord, span};
[self.mapView setRegion:region];
CLLocationCoordinate2D annotationCoord;
annotationCoord.latitude = 18.520430;
annotationCoord.longitude = 73.856744;
self.lblLongitude.text = [NSString stringWithFormat:#"%f ", annotationCoord.latitude];
self.lblLatitude.text = [NSString stringWithFormat:#" %f", annotationCoord.longitude];
MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc] init];
annotationPoint.coordinate = annotationCoord;
annotationPoint.title = #"Mindbowser";
annotationPoint.subtitle = #"Pune Headquater's";
[_mapView addAnnotation:annotationPoint];
}
You need to implement the map's delegate method and set the delegate.
- (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]])
{
MKPinAnnotationView *pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if (!pinView)
{
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.pinColor = MKPinAnnotationColorGreen;
}
else {
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
In your viewDidLoad() , write the following code
_mapView.delegate = self;
This may help you.
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{
MKPinAnnotationView *annotationView = nil;
if(![annotation isKindOfClass:[MKUserLocation class]]){
annotationView=[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:#"pin"];
annotationView.pinColor = MKPinAnnotationColorGreen;
}
return annotationView;
}
Implement the delegate method below and return MKAnnotationView by assigning the pinTintColor it is available from iOS 9.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString *annotaionIdentifier=#"annotationIdentifier";
MKPinAnnotationView *aView=(MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:annotaionIdentifier ];
if (aView==nil) {
aView=[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:annotaionIdentifier];
aView.pinTintColor = [UIColor yellowColor];//from iOS 9, you can pass in any color you want.
//aView.pinColor = MKPinAnnotationColorPurple //if iOS is less than 9.0
aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
aView.animatesDrop=TRUE;
aView.canShowCallout = YES;
aView.calloutOffset = CGPointMake(-5, 5);
}
return aView;
}
To change color while adding annotation, check below method.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation
(id<MKAnnotation>)annotation {
static NSString *identifier = #"PinAnnotationIdentifier";
MKPinAnnotationView *pinAnnotation = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if(!pinAnnotation) {
pinAnnotation = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
}
pinAnnotation.pinColor = MKPinAnnotationColorGreen; //Color
return pinAnnotation;
}
Use below method for changing color on select and deselect.
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKPinAnnotationView *)view {
view.pinColor = MKPinAnnotationColorRed;
}
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKPinAnnotationView *)view {
view.pinColor = MKPinAnnotationColorGreen;
}

Selected map pins show the same coordinate

I am trying get the coordinate of each pin I select on my map. Pins are the local search results that users search on the map. I have an issue that every pin I select it give me the same value. Can anyone help me with this please? Thanks in advance.
- (IBAction)searchAction:(id)sender {
[sender resignFirstResponder];
[self.mapView removeAnnotations:[self.mapView annotations]];
[self performSearch]; }
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
// If it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
MKPinAnnotationView *mypin = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:#"current"];
//mypin.pinColor = MKPinAnnotationColorPurple;
mypin.backgroundColor = [UIColor clearColor];
UIButton *goToDetail = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
mypin.rightCalloutAccessoryView = goToDetail;
mypin.draggable = NO;
mypin.highlighted = YES;
mypin.animatesDrop = TRUE;
mypin.canShowCallout = YES;
return mypin;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
MKPointAnnotation *annotation = view.annotation;
self.tappedCoord = annotation.coordinate;
// Longs are the same for every pin I select
NSLog(#"%f", [[view annotation] coordinate].longitude);
}
- (void)performSearch {
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = _searchText.text;
request.region = _mapView.region;
self.matchingItems = [[NSMutableArray alloc] init];
MKLocalSearch *search = [[MKLocalSearch alloc]initWithRequest:request];
[search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
if (response.mapItems.count == 0)
NSLog(#"No Matches");
else
for (MKMapItem *item in response.mapItems)
{
[self.matchingItems addObject:item];
MKPointAnnotation *annotation = [[MKPointAnnotation alloc]init];
annotation.coordinate = item.placemark.coordinate;
annotation.title = item.name;
annotation.subtitle = [NSString stringWithFormat:#"%#, %# %#",
item.placemark.addressDictionary[#"Street"],
item.placemark.addressDictionary[#"State"],
item.placemark.addressDictionary[#"ZIP"]];
//NSLog(#"%#", item.placemark.addressDictionary);
[_mapView addAnnotation:annotation];
}
}];
}

How to add an UIButton to placemark? ios objective c

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

Resources