1 FindMe应用

1.1 问题

MapKit框架可以用于创建现场交互的地图来显示用户想要设备显示的任何位置,包括用户的当前位置,甚至可以进行标记并查看地图上的标注信息。CoreLocation框架主要用于确定物理位置,通过三种技术来实现:GPS、蜂窝基站定位和WPS,GPS是这三种中最精确。本案例使用MapKit和CoreLocation框架完成一款地图应用,显示自身的位置并添加视图标注,如图-1所示:

图-1

1.2 方案

首先创建一个SingleViewApplication应用,需要将CoreLocation和MapKit框架添加到项目中。

然后在Storyboard文件中搭建界面,从对象库中拖拽一个MapView控件到场景中,调整地图视图的尺寸使宽度占满整个大视图,通过连线的方式将MapView控件的delegate设置为ViewController。

场景的下方再拖放一个Label控件和Button控件。分别将场景中的MapView控件、Label控件以及Button控件关联成ViewController的输出口属性mapView、progressLabel和button,另外再将Button控件关联成ViewController的动作方法findMe:,当点击按钮时该方法被调用开始更新定位。

接下来创建一个类Annotation用来保存标注对象,该类有一个必须的属性CLLocationCoordinate2D类型的coordinate,用来记录标注的位置,然后通过重写属性title和subTitle的setter方法设置标题和子标题的内容。

完成以上步骤后在ViewController类扩展中定义一个CLLocationManager类型的locationManager属性,并且ViewController需要遵守MKMapViewDelegate和CLLocationManagerDelegate协议。在viewDidLoad方法中将self.mapView的showsUserLocation属性设置为YES,允许显示当前用户的位置。

然后实现findMe:方法,该方法中设置self.locationManager的相关属性并将delegate设置为ViewController,通过调用startUpdatingLocation方法开始更新地图数据,然后更新label的显示内容。

接下来实现locationManager:didUpdateLocations:协议方法,该方法在每次更新位置时调用,该方法中通过locations参数获取到当前位置,并通过当前位置创建一个显示区域,添加标注更新label的显示内容。

最后实现mapView:viewForAnnotation:协议方法,当mapView需要一个标注视图时将调用该方法,在该方法中创建一个标注视图,并添加到地图上。

1.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:搭建界面

首先创建一个SingleViewApplication应用,需要将CoreLocation和MapKit框架添加到项目中。

然后在Storyboard文件中搭建界面,从对象库中拖拽一个MapView控件到场景中,调整地图视图的尺寸使宽度占满整个大视图,通过连线的方式将MapView控件的delegate设置为ViewController,如图-2所示:

图-2

场景的下方再拖放一个Label控件和Button控件。分别将场景中的MapView控件、Label控件以及Button控件关联成ViewController的输出口属性mapView、progressLabel和button,另外再将Button控件关联成ViewController的动作方法findMe:,当点击按钮时该方法被调用开始更新定位,代码如下所示:

  1. @interface ViewController ()
  2. @property (weak, nonatomic) IBOutlet MKMapView *mapView;
  3. @property (weak, nonatomic) IBOutlet UILabel *progressLabel;
  4. @property (weak, nonatomic) IBOutlet UIButton *button;
  5. @end

在Storyboard中完成的界面如图-3所示:

图-3

步骤二:创建标注类Annotation

创建一个类Annotation用来保存标注对象,该类继承至NSObjet,它有一个必须的属性CLLocationCoordinate2D类型的coordinate,用来记录标注的位置,然后通过重写属性title和subTitle的setter方法设置标题和子标题的内容,代码如下所示:

 
  1. //Annotation.h文件
  2. @interface Annotation : NSObject<MKAnnotation>
  3. @property (nonatomic,assign) CLLocationCoordinate2D coordinate;
  4. @end
  5. //Annotation.m文件
  6. @implementation Annotation
  7. -(NSString *)title {
  8. NSString *string = @"You are here";
  9. return string;
  10. }
  11. -(NSString *)subtitle {
  12. NSString *string = @"您当前位置";
  13. return string;
  14. }
  15. @end

步骤三:实现地图定位和添加标注视图

在ViewController类扩展中定义一个CLLocationManager类型的locationManager属性,并且ViewController需要遵守MKMapViewDelegate和CLLocationManagerDelegate协议,代码如下所示:

  1. @interface ViewController ()<MKMapViewDelegate,CLLocationManagerDelegate,UIAlertViewDelegate>
  2. @property (weak, nonatomic) IBOutlet MKMapView *mapView;
  3. @property (weak, nonatomic) IBOutlet UILabel *progressLabel;
  4. @property (weak, nonatomic) IBOutlet UIButton *button;
  5. @property (nonatomic,strong) CLLocationManager *locationManager;
  6. @end
  7. //初始化属性locationManager
  8. -(CLLocationManager *)locationManager {
  9. if (!_locationManager) {
  10. _locationManager = [[CLLocationManager alloc]init];
  11. }
  12. return _locationManager;
  13. }

在viewDidLoad方法中设置self.mapView的类型,并将self.mapView的showsUserLocation属性设置为YES,允许显示当前用户的位置,代码如下所示:

  1. - (void)viewDidLoad {
  2. [super viewDidLoad];
  3. self.mapView.mapType = MKMapTypeStandard;
  4. self.mapView.showsUserLocation = YES;
  5. }

然后实现findMe:方法,该方法中设置self.locationManager的相关属性并将delegate设置为ViewController,通过调用startUpdatingLocation方法开始更新地图数据,然后更新label的显示内容,代码如下所示:

  1. - (IBAction)findMe:(UIButton *)sender {
  2. //设置委托对象
  3. self.locationManager.delegate = self;
  4. //设置最佳精确度
  5. self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
  6. //开始更新
  7. [self.locationManager requestAlwaysAuthorization];
  8. [self.locationManager requestWhenInUseAuthorization];
  9. [self.locationManager startUpdatingLocation];
  10. //设置标签显示内容
  11. self.progressLabel.text = @"Delermining Current Location";
  12. sender.hidden = YES;
  13. }

接下来实现locationManager:didUpdateLocations:协议方法,该方法在每次更新位置时调用,该方法中通过locations参数获取到当前位置,并通过当前位置创建一个显示区域,添加标注更新label的显示内容,代码如下所示:

  1. -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
  2. //获取当前位置
  3. CLLocation *newLocation = locations[0];
  4. NSLog(@"%@",newLocation);
  5. //设置显示区域
  6. MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 2000, 2000);
  7. //调整区域以适合地图视图显示的宽高比
  8. MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:viewRegion];
  9. //将调整后的区域显示在地图视图上面
  10. [self.mapView setRegion:adjustedRegion animated:YES];
  11. manager.delegate = self;
  12. //由于更新位置是一个比较耗电量的操作,在不必要更新时可以关闭locationManager
  13. [manager stopUpdatingLocation];
  14. //更新标签显示
  15. self.progressLabel.text = @"Recerse Geocoding Location";
  16. //添加标注
  17. Annotation *annotation = [[Annotation alloc]init];
  18. annotation.coordinate = newLocation.coordinate;
  19. [self.mapView addAnnotation:annotation];
  20. self.progressLabel.text = @"Location Determined";
  21. }

最后实现mapView:viewForAnnotation:协议方法,当mapView需要一个标注视图时将调用该方法,在该方法中创建一个标注视图,并添加到地图上,代码如下所示:

  1. -(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
  2. static NSString *placemarkIdentifier = @"Map Location Identifier";
  3. if ([annotation isKindOfClass:[Annotation class]]) {
  4. MKPinAnnotationView *annotationView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:placemarkIdentifier];
  5. if (!annotationView) {
  6. annotationView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:placemarkIdentifier];
  7. }else {
  8. annotationView.annotation = annotation;
  9. }
  10. annotationView.enabled = YES;
  11. annotationView.animatesDrop = YES;
  12. annotationView.pinColor = MKPinAnnotationColorPurple;
  13. annotationView.canShowCallout = YES;
  14. //为了能够看到显示过程延迟5秒将标注视图添加到界面上
  15. [self performSelector:@selector(openCallout:) withObject:annotation afterDelay:5];
  16. self.progressLabel.text = @"Creating Annotation";
  17. return annotationView;
  18. }
  19. return nil;
  20. }
  21. //选中标注
  22. -(void)openCallout:(id<MKAnnotation>)annotation {
  23. self.progressLabel.text = @"Show Annotation";
  24. [self.mapView selectAnnotation:annotation animated:YES];
  25. }

当遇到错误和警告时同样可以通过实现MKMapViewDelegate协议和CLLocationManagerDelegate协议中的方法来提醒用户,代码如下所示:

  1. -(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
  2. NSString *errorType = (error.code == kCLErrorDenied)?@"Access Denied":@"Unknow Error";
  3. UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"Error getting Location" message:errorType delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
  4. [av show];
  5. }
  6. -(void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error {
  7. UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"Error loading map" message:[error description] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
  8. [av show];
  9. NSLog(@"%@",[error description]);
  10. }
  11. //UIAlertViewDelegate
  12. -(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
  13. self.progressLabel.text = @"";
  14. self.button.hidden = NO;
  15. }

完成效果如图-4、图-5、图-6所示:

图-4

图-5

图-6

1.4 完整代码

本案例中,ViewController.m文件中的完整代码如下所示:

 
  1. #import "ViewController.h"
  2. #import "Annotation.h"
  3. @interface ViewController ()<MKMapViewDelegate,CLLocationManagerDelegate,UIAlertViewDelegate>
  4. @property (weak, nonatomic) IBOutlet MKMapView *mapView;
  5. @property (weak, nonatomic) IBOutlet UILabel *progressLabel;
  6. @property (weak, nonatomic) IBOutlet UIButton *button;
  7. @property (nonatomic,strong) CLLocationManager *locationManager;
  8. @end
  9. @implementation ViewController
  10. - (void)viewDidLoad {
  11. [super viewDidLoad];
  12. self.mapView.mapType = MKMapTypeStandard;
  13. self.mapView.showsUserLocation = YES;
  14. }
  15. -(CLLocationManager *)locationManager {
  16. if (!_locationManager) {
  17. _locationManager = [[CLLocationManager alloc]init];
  18. }
  19. return _locationManager;
  20. }
  21. - (IBAction)findMe:(UIButton *)sender {
  22. //设置委托对象
  23. self.locationManager.delegate = self;
  24. //设置最佳精确度
  25. self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
  26. //开始更新
  27. [self.locationManager requestAlwaysAuthorization];
  28. [self.locationManager requestWhenInUseAuthorization];
  29. [self.locationManager startUpdatingLocation];
  30. //设置标签显示内容
  31. self.progressLabel.text = @"Delermining Current Location";
  32. sender.hidden = YES;
  33. }
  34. //CLLocationManagerDelegate协议方法
  35. -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
  36. //获取当前位置
  37. CLLocation *newLocation = locations[0];
  38. NSLog(@"%@",newLocation);
  39. //设置显示区域
  40. MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 2000, 2000);
  41. //调整区域以适合地图视图显示的宽高比
  42. MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:viewRegion];
  43. //将调整后的区域显示在地图视图上面
  44. [self.mapView setRegion:adjustedRegion animated:YES];
  45. manager.delegate = self;
  46. //由于更新位置是一个比较耗电量的操作,在不必要更新时可以关闭locationManager
  47. [manager stopUpdatingLocation];
  48. //更新标签显示
  49. self.progressLabel.text = @"Recerse Geocoding Location";
  50. //添加标注
  51. Annotation *annotation = [[Annotation alloc]init];
  52. annotation.coordinate = newLocation.coordinate;
  53. [self.mapView addAnnotation:annotation];
  54. self.progressLabel.text = @"Location Determined";
  55. }
  56. -(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
  57. NSString *errorType = (error.code == kCLErrorDenied)?@"Access Denied":@"Unknow Error";
  58. UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"Error getting Location" message:errorType delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
  59. [av show];
  60. }
  61. //MapViewDelegate方法
  62. //当mapView需要一个标注视图时将调用该方法,在该方法中创建一个标注视图
  63. -(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
  64. static NSString *placemarkIdentifier = @"Map Location Identifier";
  65. if ([annotation isKindOfClass:[Annotation class]]) {
  66. MKPinAnnotationView *annotationView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:placemarkIdentifier];
  67. if (!annotationView) {
  68. annotationView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:placemarkIdentifier];
  69. }else {
  70. annotationView.annotation = annotation;
  71. }
  72. annotationView.enabled = YES;
  73. annotationView.animatesDrop = YES;
  74. annotationView.pinColor = MKPinAnnotationColorPurple;
  75. annotationView.canShowCallout = YES;
  76. //为了能够看到显示过程延迟5秒将标注视图添加到界面上
  77. [self performSelector:@selector(openCallout:) withObject:annotation afterDelay:5];
  78. self.progressLabel.text = @"Creating Annotation";
  79. return annotationView;
  80. }
  81. return nil;
  82. }
  83. //选中标注
  84. -(void)openCallout:(id<MKAnnotation>)annotation {
  85. self.progressLabel.text = @"Show Annotation";
  86. [self.mapView selectAnnotation:annotation animated:YES];
  87. }
  88. -(void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error {
  89. UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"Error loading map" message:[error description] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
  90. [av show];
  91. NSLog(@"%@",[error description]);
  92. }
  93. //UIAlertViewDelegate
  94. -(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
  95. self.progressLabel.text = @"";
  96. self.button.hidden = NO;
  97. }
  98. @end

本案例中,Annotation.h文件中的完整代码如下所示:

 
  1. #import <Foundation/Foundation.h>
  2. #import <MapKit/MapKit.h>
  3. @interface Annotation : NSObject<MKAnnotation>
  4. @property (nonatomic,assign) CLLocationCoordinate2D coordinate;
  5. @end

本案例中,Annotation.m文件中的完整代码如下所示:

 
  1. #import "Annotation.h"
  2. @implementation Annotation
  3. -(NSString *)title {
  4. NSString *string = @"You are here";
  5. return string;
  6. }
  7. -(NSString *)subtitle {
  8. NSString *string = @"您当前位置";
  9. return string;
  10. }
  11. @end

地图和定位 、 iCloud的更多相关文章

  1. iOS开发系列--地图与定位

    概览 现在很多社交.电商.团购应用都引入了地图和定位功能,似乎地图功能不再是地图应用和导航应用所特有的.的确,有了地图和定位功能确实让我们的生活更加丰富多彩,极大的改变了我们的生活方式.例如你到了一个 ...

  2. iOS开发之地图与定位

    无论是QQ还是微信的移动客户端都少不了定位功能,之前在微信demo中没有添加定位功能,今天就写个定位的小demo来了解一下定位和地图的东西.地图和定位看上去是挺高大上一东西,其实用法比TableVie ...

  3. [OC][地图] 高德地图之定位初探(一)

    使用前的说明 高德地图开放平台的iOS定位模块网址-->http://lbs.amap.com/api/ios-location-sdk/summary/ 高德地图有Web端.android平台 ...

  4. iOS进阶_地图上定位的标志——大头针

    一.添加大头针 地图使用的框架是MapKit 大头针走的是MKAnnotation协议 /* 注意:因为是满足协议MKAnnotation,所以没有MKAnnotation的系统大头针类,必须自定义大 ...

  5. 地图、定位 CLLocationManager CLGeocoder CLPlacemark

    地图.定位 一.基本知识点 定位: 1.info.plist文件设置 ios8以后,使用定位需要在info.plist文件中添加两个字段NSLocationAlwaysUsageDescription ...

  6. Android 百度地图API 定位 导航

    看看这个利用百度地图定位并实现目的地导航的Demo. 首先看实现效果:                          进 入后首先会得到当前位置,在地图上显示出来.在输入框中输入目的地后,就会在地 ...

  7. ios开发——实用技术OC篇&地图与定位

    地图与定位 11.1 iOS定位服务 11.2 iOS地图 11.3 Web地图 1 iOS定位服务 iOS中有三个定位服务组件: Wifi定位,通过查询一个Wifi路由器的地理位置的信息.比较省电, ...

  8. 在Fragment中实现百度地图,定位到当前位置(基于SDKv2.1.0)

    使用最新版本的百度地图需要注意的几个地方: 1.libs文件夹下要有android-support-v4.jar.baidumapapi_v2_1_0.jar.locSDK_3.1.jar三个jar包 ...

  9. iOS中的地图和定位

    文章摘自http://www.cnblogs.com/kenshincui/p/4125570.html#location  如有侵权,请联系删除. 概览 现在很多社交.电商.团购应用都引入了地图和定 ...

  10. AngularJS进阶(十九)在AngularJS应用中集成百度地图实现定位功能

    在AngularJS应用中集成百度地图实现定位功能 注:请点击此处进行充电! 前言 根据项目需求,需要实现手机定位功能,考虑到百度业务的强大能力,遂决定使用百度地图第三方服务. 添加第三方模块的步骤与 ...

随机推荐

  1. Zero Copy

    原文出处: http://www.ibm.com/developerworks/library/j-zerocopy/ 传统的I/O 使用传统的I/O程序读取文件内容, 并写入到另一个文件(或Sock ...

  2. 《BI那点儿事》数据流转换——透视

    这个和T-SQL中的PIVOT和UNPIVOT的作用是一样的.数据透视转换可以将数据规范或使它在报表中更具可读性. 通过透视列值的输入数据,透视转换将规范的数据集转变成规范程度稍低.但更为简洁的版本. ...

  3. phonegap 3.3教程 地理信息api教程

    一 准备工作 phonegap3.3的地理信息教程.从零开始,首先要新建一个项目从命令行启动 可以看到这是默认的生成的www目录,在这个目录里是最原始的html文件,编译的时候在根据这里的文件生成an ...

  4. php支付宝在线支付接口开发教程【转】

    php支付宝在线支付接口开发教程 这篇文章主要为大家详细介绍了php支付宝在线支付接口开发教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下   1.什么是第三方支付 所谓第三方支付,就是一些和各 ...

  5. ArrayList 如何增加大小

    JDK1.8 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; transient Object[] elem ...

  6. Xcode创建Object-C程序

    一. Xcode 环境安装 与 工程创建 1. 下载环境 相关资源下载 : -- IOS 相关资料下载页面 :  https://developer.apple.com/devcenter/ios/i ...

  7. java程序

    package Dome3; import java.awt.Button; import java.awt.FlowLayout; import java.awt.Frame; import jav ...

  8. 安装mongodb

    安装mongodb的时候遇到一些麻烦 首先将安装包下下来 安装的是windows版本的 将bin文件夹加入环境变量后通过mongod和mongo指令就可以进行操作,很方便 用指令mongod --db ...

  9. 并发编程 04——闭锁CountDownLatch 与 栅栏CyclicBarrier

    Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...

  10. Linux设备驱动中的并发控制

    1.并发是指多个执行单元同时.并行的执行.并发的执行单元对共享资源的访问很容易导致竞态. 在 Linux 内核中,主要的竞态发生于如下几种情况: ①对称多处理器(SMP)的多个 CPU ②单CPU内进 ...