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

MapSearch 阅读随笔的更多相关文章

  1. 《UML大战需求分析》阅读随笔(一)

    UML:Unified Modeling Language(统一建模语言) 作为我专业学科里的一门语言,其目的就是交流,同客户交流,同自己交流. 用图像和文字,详细地讲解将要做的工程的 需求和功能细节 ...

  2. 《重构网络-SDN架构与实现》阅读随笔

    <重构网络-SDN架构与实现>: SDNLAB <重构网络-SDN架构与实现>新书有奖试读活动 资源下载 随笔 有幸拜读了李呈前辈和杨泽卫杨老师的作品<重构网络-SDN架 ...

  3. Google Java 风格 阅读随笔

    官方文档:Google Java Style 中文翻译版:Google Java编程风格指南, Hawstein's Blog 可以先看官方文档,遇到不确定有疑问的,可以再对照翻译版本阅读,加深理解. ...

  4. sqlalchemy源代码阅读随笔(2)

    这次阅读的,是Strategies.py文件. 文件自身,是这么描述的: """Strategies for creating new instances of Engi ...

  5. Java核心技术卷阅读随笔--第3章【Java 的基本程序设计结构】

    Java 的基本程序设计结构 现在, 假定已经成功地安装了 JDK,并且能够运行第 2 章中给出的示例程序.我们从现在开始将介绍 Java 应用程序设计.本章主要介绍程序设计的基本概念(如数据类型.分 ...

  6. Java核心技术卷阅读随笔--第4章【对象与类】

    对 象 与 类 4.1 面向对象程序设计概述 面向对象程序设计(简称 OOP) 是当今主流的程序设计范型, 它已经取代了 20 世纪 70 年代的" 结构化" 过程化程序设计开发技 ...

  7. Java核心技术卷阅读随笔--第2章【Java 程序设计环境】

    Java 程序设计环境 本章主要介绍如何安装 Java 开发工具包( JDK ) 以及如何编译和运行不同类型的程序: 控制台程序. 图形化应用程序以及 applet.运行 JDK 工具的方法是在终端窗 ...

  8. 《UML大战需求分析》阅读随笔(六)

    在我们做的代码设计中分为系统设计和程序设计.程序设计是系统设计中模拟程序的执行逻辑,定义客户机服务器对象合作的框架的那个部分.程序和事务设计中,作者讲述到程序和事务设计将系统设计制品放在一起,并作为系 ...

  9. 《UML大战需求分析》阅读随笔(五)

    在处理复杂事物的时候,用到一种基本手段就是抽象.抽象的目的是区别事物之间的本质和不同,面向对象编程(OOP)的实质就是利用 类和对象来建立抽象模型. 类表示对象的类别,是创建对象的蓝本.建立一个事物的 ...

随机推荐

  1. URAL1513. Lemon Tale(dp)

    1513 这题好久之前就看过了,悲催的是当时看题解都没看懂,今天又看了看so easy... n个B里不能出现超过连续k个L的情况 一维递推就可以 两种情况 1.dp[i] += dp[i-1] 在i ...

  2. WebView中Js与Android本地函数的相互调用

    介绍 随着Html5的普及,html在表现力上不一定比原生应用差,并且有很强的扩展兼容性,所以越来越多的应用是采用Html与Android原生混合开发模式实现. 既然要实现混合开发,那么Js与Andr ...

  3. hdu3333(线段树)

    区间更新,单点查询. hdu3333 #include <iostream> #include <stdio.h> #include <string.h> #inc ...

  4. UVa 839 (递归方式读取二叉树) Not so Mobile

    题意: 递归的方式输入一个树状天平(一个天平下面挂的不一定是砝码还可能是一个子天平),判断这个天平是否能满足平衡条件,即W1 * D1 == W2 * D2. 递归的方式处理输入数据感觉很巧妙,我虽然 ...

  5. 51nod1349 最大值

    还是傻叉单调栈 #include<cstdio> #include<cstring> #include<cctype> #include<algorithm& ...

  6. IOS中封装一个View的思路

    一.封装一个View的思路 1.将View内部的业务逻辑(显示内容)封装到View中 2.一般情况下,View的位置应该由父控件来决定,也就是位置不应该固定死在View内部 3.至于View的宽高,根 ...

  7. POJ 1422 Air Raid (最小路径覆盖)

    题意 给定一个有向图,在这个图上的某些点上放伞兵,可以使伞兵可以走到图上所有的点.且每个点只被一个伞兵走一次.问至少放多少伞兵. 思路 裸的最小路径覆盖. °最小路径覆盖 [路径覆盖]在一个有向图G( ...

  8. HDU 5375 Gray code 格雷码(水题)

    题意:给一个二进制数(包含3种符号:'0'  '1'  '?'  ,问号可随意 ),要求将其转成格雷码,给一个序列a,若转成的格雷码第i位为1,则得分+a[i].求填充问号使得得分最多. 思路:如果了 ...

  9. HDU 3666 THE MATRIX PROBLEM (差分约束,最短路)

    题意: 给一个n*m矩阵,每个格子上有一个数字a[i][j],给定L和U,问:是否有这样两个序列{a1...an}和{b1...bn},满足 L<=a[i][j]*ai/bj<=U .若存 ...

  10. erl0009 - erlang 读取时间瓶颈解决办法

    读取时间erlang提供有两种方式: 1.erlang:now(); 2.os:timestamp(); 以上两种方式由于erlang系统需要保证读取精度,当并发读取的时候会引起加锁.系统频繁读取时间 ...