Search code examples
iosobjective-cxcodemkmapviewmapkitannotation

Safari Search From Any Given Point Annotation in MapView


Alright, I'm going to do my very best at explaining this. The method "searchBarSearchButtonClicked:" accesses a singleton pattern from the data source which provides an MKLocalSearch. We then set up the point annotations in our MapViewController using the shared instance. All of this works perfectly. But what I cant figure out is how to run a safari search, from any given point annotation's title.

I have a button in my annotation view. Within the action of that button, I'm able to open safari, and run the search, but the search doesn't match the annotation title. What's happening right now is that it appends a random annotation title to all of the points of interest displayed on the map. Essentially, the button doesn't know which title goes with each point of interest.

User Story: So say I run a search for "pizza" on a map, I get Pins for each pizza restaurant around that users location. When I tap on the safari search button in the annotation view, the string that gets appended to the search is one of the pizza restaurants names, but it's not the name that matches the annotation view that I clicked on. Say I clicked on dominos or little caesar's both searches done in safari would come back as pizza hut. I know the problem here, but I don't have a clue on how to fix it.

The code I have within the action method for the safari button (leftButtonAnnotationPressed:) is simply just for testing to see what output I'm getting in the console when I click on the button. And the problem lies (I assume) with the *appendString. That's about as detailed as I can get, and of course, the code is below. You will notice the last result from the map search log gets appended to the search, no matter what location you tap on, in the output from the leftButtonAnnoationPressed method.

Annotations

-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
    [self.searchBarMap resignFirstResponder];

[[DataSource sharedInstance] requestNewItemsWithText:self.searchBarMap.text withRegion:self.mapView.region completion:^{
    for (MKMapItem *items in [DataSource sharedInstance].matchingItems){
        self.pointAnnotation = [[MKPointAnnotation alloc] init];
        self.pointAnnotation.coordinate = items.placemark.coordinate;
        self.pointAnnotation.title = items.name;
        [self.mapView addAnnotation:self.pointAnnotation];
        self.storedItemNames = items.name;
        NSLog(@"%@", self.storedItemNames);
    }
  }];
}

Safari Search Button Action

-(void)leftButtonAnnotationPressed:(UIButton *)sender {
    NSString *appendString = self.pointAnnotation.title;
    NSString *urlString = @"http://www.google.com/search?q=";
    NSString *appendedUrlString = [urlString stringByAppendingString:appendString];
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:appendedUrlString]];

    NSLog(@"%@", appendedUrlString);
}

Output from Map Search

2015-07-10 17:42:54.092 BlocSpot[1324:256489] Blondie's Pizza
2015-07-10 17:42:54.094 BlocSpot[1324:256489] Uncle Vito's Pizza
2015-07-10 17:42:54.096 BlocSpot[1324:256489] Zero Zero
2015-07-10 17:42:54.098 BlocSpot[1324:256489] Postrio
2015-07-10 17:42:54.100 BlocSpot[1324:256489] Cybelle's Pizza & Ice Cream
2015-07-10 17:42:54.102 BlocSpot[1324:256489] California Pizza Kitchen
2015-07-10 17:42:54.103 BlocSpot[1324:256489] zpizza
2015-07-10 17:42:54.105 BlocSpot[1324:256489] Pachino Trattoria & Pizzeria
2015-07-10 17:42:54.107 BlocSpot[1324:256489] Milan Pizza
2015-07-10 17:42:54.109 BlocSpot[1324:256489] Buca di Beppo Italian Restaurant

Output from leftButtonAnnotationPressed: (which string actually gets appended)

2015-07-10 17:42:59.555 BlocSpot[1324:256489] http://www.google.com/search?q=Buca di Beppo Italian Restaurant
2015-07-10 17:43:00.967 BlocSpot[1324:256489] http://www.google.com/search?q=Buca di Beppo Italian Restaurant
2015-07-10 17:43:01.982 BlocSpot[1324:256489] http://www.google.com/search?q=Buca di Beppo Italian Restaurant
2015-07-10 17:43:08.141 BlocSpot[1324:256489] http://www.google.com/search?q=Buca di Beppo Italian Restaurant
2015-07-10 17:43:10.374 BlocSpot[1324:256489] http://www.google.com/search?q=Buca di Beppo Italian Restaurant
2015-07-10 17:43:12.111 BlocSpot[1324:256489] http://www.google.com/search?q=Buca di Beppo Italian Restaurant
2015-07-10 17:43:14.395 BlocSpot[1324:256489] http://www.google.com/search?q=Buca di Beppo Italian Restaurant

UPDATE

    MKPointAnnotation *annotation = [self.mapView.selectedAnnotations objectAtIndex:([self.mapView.selectedAnnotations count]) -1];
    NSString *appendString = annotation.title;
    NSString *urlString = @"http://www.google.com/search?q=";
    NSString *appendedUrlString = [urlString stringByAppendingString:appendString];
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:appendedUrlString]];

    NSLog(@"appended string: %@", appendedUrlString);
}

Progress

MKPointAnnotation *annotation = [self.mapView.selectedAnnotations objectAtIndex:([self.mapView.selectedAnnotations count]) -1];
NSString *appendString = annotation.title;

This little line of code seems to do the trick. As of right now I'm logging the correct output to the console, so it works. I'm a little confused about the -1, and what it does. So if anybody has any comments regarding the -1 in *annotation please feel free to comment. More to come once the new view controller and webView perform the search.


Solution

  • MKMapView provides a property called .selectedAnnotations. You can call this on your mapView in order to get the selected title, and append it to a string. Here we are using it to run a web search and are appending it to a URL string.

    The property declaration of .selectedAnnotations looks something like this:

    @property(nonatomic, copy) NSArray *selectedAnnotations
    

    The property is declared for you by the MKMapView delegate. In other words, you do not need to declare it yourself. Just send the message to your mapView: self.mapView.selectedAnnotations, and make sure your class conforms to MKMapViewDelegate.

    MKPointAnnotation *annotation = [self.mapView.selectedAnnotations objectAtIndex:([self.mapView.selectedAnnotations count]) -1];
    NSString *appendString = annotation.title;
    NSString *urlString = @"http://www.google.com/search?q=";
    NSString *appendedUrlString = [urlString stringByAppendingString:appendString];
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:appendedUrlString]];
    
    NSLog(@"appended string: %@", appendedUrlString);
    }
    

    The -1 at the end of the *annotation statement works like this:

    .selectedAnnotations is declared as an NSArray, so we can call objectAtIndex on it. The index is zero based, which means the first item is 0. The count is one based, which means the first item is 1. So the -1 is needed to make the shift from 1 based to zero based. In other words, the count and index need to match up.