MapSearch 阅读随笔
MapSearch
https://developer.apple.com/library/ios/samplecode/MapSearch/Introduction/Intro.html#//apple_ref/doc/uid/DTS40013332
//1.#import <MapKit/MapKit.h> //引入头文件
#import <CoreLocation/CoreLocation.h>
//遵循协议
<CLLocationManagerDelegate, UISearchBarDelegate>
//2. 声明 属性
@interface MyTableViewController ()
@property (nonatomic, assign) MKCoordinateRegion boundingRegion;
@property (nonatomic, strong) MKLocalSearch *localSearch;
@property (nonatomic, weak) IBOutlet UIBarButtonItem *viewAllButton;
@property (nonatomic, strong) CLLocationManager *locationManager;
@property (nonatomic) CLLocationCoordinate2D userCoordinate;
@property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
@end
//3. 初始化 locationManager
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
}
//4. UITableView delegate methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.places count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier forIndexPath:indexPath];
MKMapItem *mapItem = [self.places objectAtIndex:indexPath.row];
cell.textLabel.text = mapItem.name;
return cell;
}
//5.点击搜索按钮后执行
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
// Check if location services are available
if ([CLLocationManager locationServicesEnabled] == NO) {
NSLog(@"%s: location services are not available.", __PRETTY_FUNCTION__);
// Display alert to the user.
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Location services"
message:@"Location services are not enabled on this device. Please enable location services in settings."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"Dismiss" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}]; // Do nothing action to dismiss the alert.
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
return;
}
// Request "when in use" location service authorization.
// If authorization has been denied previously, we can display an alert if the user has denied location services previously.
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
[self.locationManager requestWhenInUseAuthorization];
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
NSLog(@"%s: location services authorization was previously denied by the user.", __PRETTY_FUNCTION__);
// Display alert to the user.
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Location services"
message:@"Location services were previously denied by the user. Please enable location services for this app in settings."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"Dismiss" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}]; // Do nothing action to dismiss the alert.
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
return;
}
// Start updating locations.
self.locationManager.delegate = self;
[self.locationManager startUpdatingLocation];
}
//6. 获取定位信息后根据位置信息搜索周围地点
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
// Remember for later the user's current location.
CLLocation *userLocation = locations.lastObject;
self.userCoordinate = userLocation.coordinate;
[manager stopUpdatingLocation]; // We only want one update.
manager.delegate = nil; // We might be called again here, even though we
// called "stopUpdatingLocation", so remove us as the delegate to be sure.
// We have a location now, so start the search.
[self startSearch:self.searchBar.text];
}
- (void)startSearch:(NSString *)searchString {
if (self.localSearch.searching)
{
[self.localSearch cancel];
}
// Confine the map search area to the user's current location.
MKCoordinateRegion newRegion;
newRegion.center.latitude = self.userCoordinate.latitude;
newRegion.center.longitude = self.userCoordinate.longitude;
// Setup the area spanned by the map region:
// We use the delta values to indicate the desired zoom level of the map,
// (smaller delta values corresponding to a higher zoom level).
// The numbers used here correspond to a roughly 8 mi
// diameter area.
//
newRegion.span.latitudeDelta = 0.112872;
newRegion.span.longitudeDelta = 0.109863;
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = searchString;
request.region = newRegion;
MKLocalSearchCompletionHandler completionHandler = ^(MKLocalSearchResponse *response, NSError *error) {
if (error != nil) {
NSString *errorStr = [[error userInfo] valueForKey:NSLocalizedDescriptionKey];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Could not find places"
message:errorStr
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
} else {
self.places = [response mapItems];
// Used for later when setting the map's region in "prepareForSegue".
self.boundingRegion = response.boundingRegion;
self.viewAllButton.enabled = self.places != nil ? YES : NO;
[self.tableView reloadData];
}
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
};
if (self.localSearch != nil) {
self.localSearch = nil;
}
self.localSearch = [[MKLocalSearch alloc] initWithRequest:request];
[self.localSearch startWithCompletionHandler:completionHandler];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}
//7.点击对应的cell 或者点击showAll 按钮 跳转到下一界面
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
MapViewController *mapViewController = segue.destinationViewController;
if ([segue.identifier isEqualToString:@"showDetail"]) {
// Get the single item.
NSIndexPath *selectedItemPath = [self.tableView indexPathForSelectedRow];
MKMapItem *mapItem = self.places[selectedItemPath.row];
// Pass the new bounding region to the map destination view controller.
MKCoordinateRegion region = self.boundingRegion;
// And center it on the single placemark.
region.center = mapItem.placemark.coordinate;
mapViewController.boundingRegion = region;
// Pass the individual place to our map destination view controller.
mapViewController.mapItemList = [NSArray arrayWithObject:mapItem];
} else if ([segue.identifier isEqualToString:@"showAll"]) {
// Pass the new bounding region to the map destination view controller.
mapViewController.boundingRegion = self.boundingRegion;
// Pass the list of places found to our map destination view controller.
mapViewController.mapItemList = self.places;
}
}
//8. Adjust the map to zoom/center to the annotations we want to show.
[self.mapView setRegion:self.boundingRegion animated:YES];
//9. We add the placemarks here to get the "drop" animation.
if (self.mapItemList.count == 1) {
MKMapItem *mapItem = [self.mapItemList objectAtIndex:0];
self.title = mapItem.name;
// Add the single annotation to our map.
PlaceAnnotation *annotation = [[PlaceAnnotation alloc] init];
annotation.coordinate = mapItem.placemark.location.coordinate;
annotation.title = mapItem.name;
annotation.url = mapItem.url;
[self.mapView addAnnotation:annotation];
// We have only one annotation, select it's callout.
[self.mapView selectAnnotation:[self.mapView.annotations objectAtIndex:0] animated:YES];
} else {
self.title = @"All Places";
// Add all the found annotations to the map.
for (MKMapItem *item in self.mapItemList) {
PlaceAnnotation *annotation = [[PlaceAnnotation alloc] init];
annotation.coordinate = item.placemark.location.coordinate;
annotation.title = item.name;
annotation.url = item.url;
[self.mapView addAnnotation:annotation];
}
}
//10.
- (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error {
NSLog(@"Failed to load the map: %@", error);
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
MKPinAnnotationView *annotationView = nil;
if ([annotation isKindOfClass:[PlaceAnnotation class]]) {
annotationView = (MKPinAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:@"Pin"];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"Pin"];
annotationView.canShowCallout = YES;
annotationView.animatesDrop = YES;
}
}
return annotationView;
}
//11. 界面将要消失时 removeAnnotations
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self.mapView removeAnnotations:self.mapView.annotations];
}