001-地图&定位

一、简介

  在iOS开发中,系统提供了两个框架,用来做地图和定位功能

    CoreLocation:用于地理定位

    Map Kit:用于地图展示

 

二、CoreLocation框架

1.CoreLocation的使用步骤

  1)导入CoreLocation框架(Xcode5之后可以不用导)

    

  2)导入头文件

    #import <CoreLocation/CoreLocation.h>

2.CoreLocation框架的使用须知

  1)CoreLocation框架中所有数据类型的前缀都是CL

  2)CoreLocation中使用CLLocationManager对象来做用户定位

3.模拟器模拟定位功能

4.CoreLocation的定位服务

  1)CLLocationManager(定位管理者)

    a.获取定位信息 --- iOS8要求手动请求用户授权

      ①开始定位:- (void)startUpdatingLocation;

      ②停止定位:- (void)stopUpdatingLocation;

      ③开始定位,频繁调用协议方法

        - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations;

      ④参数设置

        I.设置每个多少米定位一次(单位:米)

          属性:@property(assign, nonatomic) CLLocationDistance distanceFilter;

             // kCLLocationAccuracyBestForNavigation   最佳导航

             // kCLLocationAccuracyBest                       最精准

             // kCLLocationAccuracyNearestTenMeters    10米

             // kCLLocationAccuracyHundredMeters        百米

             // kCLLocationAccuracyKilometer                千米

             // kCLLocationAccuracyThreeKilometers       3千米

        II.定位精准度(越精准越耗电)

          属性:@property(assign, nonatomic) CLLocationAccuracy desiredAccuracy;       

    b.获取地理方向 --- 无需手动请求用户授权

      ①开始获取方向:- (void)startUpdatingHeading;

      ②停止获取方向:- (void)stopUpdatingHeading;

      ③开始获取,频繁调用协议方法

        - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading;

    c.检测用户区域 --- iOS8要求手动请求用户授权

      ①开始检测:- (void)startMonitoringForRegion:(CLRegion *)region;

      ②停止检测:- (void)stopMonitoringForRegion:(CLRegion *)region;

      ③开始检测,频繁调用协议方法

        I.指定区域内:

          - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region;

        II.指定区域外:

          - (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region;

      ④区域类(CLRegion)提供的两个子类

        I.地图圆形区域类:CLCircularRegion

        II.蓝牙信号区域类:CLBeaconRegion

  2)CLLocation(位置的地理信息)

    CLLocation是用来表示某个位置的地理信息。比如:经纬度、海拔等等

    a.经纬度(longitude:经度  latitude:纬度)

      属性:@property(readonly, nonatomic) CLLocationCoordinate2D coordinate;

    b.海拔高度(单位:米)

      属性:@property(readonly, nonatomic) CLLocationDistance altitude;

    c.航向(取值范围:0.0° ~ 359.9°  0.0°:真北方向)

      属性:@property(readonly, nonatomic) CLLocationDirection course;

    d.设备移动的速度(单位:m/s)

      属性:@property(readonly, nonatomic) CLLocationSpeed speed;

    e.水平精准度

      属性:@property(readonly, nonatomic) CLLocationAccuracy horizontalAccuracy;

    f.垂直精准度

      属性:@property(readonly, nonatomic) CLLocationAccuracy verticalAccuracy;

    g.定位返回来的时间戳

      属性:@property(readonly, nonatomic, copy) NSDate *timestamp;

    h.计算两个位置之间的距离(CLLocationDistance:double类型)

      方法:- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location;

  3)App定位功能的用户授权(对于iOS8,一些获取用户隐私的功能是需要请求用户授权)

    a.在iOS7中只要开始定位,系统自动弹出用户授权框;iOS8以后,苹果公司为保护用户隐私,一些功能需要用户手动授权

    b.授权有允许和不允许两情况,安全起见,定位前务必判断用户定位功能是否可用。方法:+ (BOOL)locationServicesEnabled;

    c.手动授权方法(只有iOS8以后才有的方法)

      ①方法1:- (void)requestAlwaysAuthorization; // 无论前台后台均有定位权限

      ②方法2:- (void)requestWhenInUseAuthorization; // 前台定位权限

    d.除方法外,还需要我们在info.plist文件中去配置一些信息

      ①对应方法1:添加字段NSLocationAlwaysUsageDescription,并说明定位目的

      ②对应方法2:添加字段NSLocationWhenInUseDescription,并说明定位目的

        

    e.现在最新出来的iOS9在定位授权方面有一个新特性:

      @property(assign, nonatomic) BOOL allowsBackgroundLocationUpdates;

      iOS9中一个项目可以存在多个定位,我们可以随时更改某一个CLLocationManager的后台定位功能

      这里如果我们需要随时改变后台定位授权的状态,除了设置allowsBackgroundLocationUpdates属性为NO,还需要配置info.plist文件:

        

      如果不按照上面plist文件去配置,在后续只要是出现动态更改后台授权的代码,程序必定会崩溃

  实例一:获取用户的定位信息

  1 // ViewController.h文件
  2 #import "ViewController.h"
  3 #import <CoreLocation/CoreLocation.h> // 导入头文件
  4 
  5 #pragma mark - 遵循定位协议<CLLocationManagerDelegate>
  6 @interface ViewController ()<CLLocationManagerDelegate>
  7 
  8 #pragma mark - CLLocationManager管理者对象
  9 @property (nonatomic, strong) CLLocationManager *manager;
 10 
 11 @end
 12 
 13 @implementation ViewController
 14 
 15 #pragma mark - 懒加载
 16 // 初始化创建CoreLocation管理者
 17 - (CLLocationManager *)manager
 18 {
 19     if (_manager == nil) {
 20         _manager = [[CLLocationManager alloc] init];
 21     }
 22     return _manager;
 23 }
 24 
 25 - (void)viewDidLoad {
 26     [super viewDidLoad];
 27     
 28     // 设置代理
 29     self.manager.delegate = self;
 30     
 31     // 参数设置
 32     // a.定位精准度(越精准越耗电)
 33     self.manager.desiredAccuracy = kCLLocationAccuracyBest;
 34     // b.每隔多少米定位一次(单位:米)
 35     // kCLLocationAccuracyBestForNavigation    最佳导航
 36     // kCLLocationAccuracyBest                 最精准
 37     // kCLLocationAccuracyNearestTenMeters     10米
 38     // kCLLocationAccuracyHundredMeters        百米
 39     // kCLLocationAccuracyKilometer            千米
 40     // kCLLocationAccuracyThreeKilometers      3千米
 41     self.manager.distanceFilter = 5;
 42     
 43     // iOS8以上:要求手动授权
 44     if ([[UIDevice currentDevice] systemVersion].floatValue >= 8.0) {
 45         // a.请求前台和后台的定位权限
 46         [self.manager requestAlwaysAuthorization];
 47         // b.请求前台的定位权限
 48         // [self.manager requestWhenInUseAuthorization];
 49     } else {
 50         // 开始定位
 51         [self.manager startUpdatingLocation];
 52     }
 53     
 54     // iOS9:同一项目中允许多个定位对象并存,可随时代码控制某个定位对象的后台定位授权
 55     if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {
 56         // 后台授权属性:allowsBackgroundLocationUpdates(YES:允许,NO:不允许)
 57         self.manager.allowsBackgroundLocationUpdates = YES;
 58     }
 59 }
 60 
 61 #pragma mark - 协议方法<CLLocationManagerDelegate>
 62 // 1.用户授权状态一经改变就会调用
 63 - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
 64 {
 65     // 授权状态status
 66     // kCLAuthorizationStatusNotDetermined       用户还未点击授权框,等待用户授权
 67     // kCLAuthorizationStatusRestricted          无法使用定位服务,该状态用户无法改变
 68     // kCLAuthorizationStatusDenied              用户拒绝或定位服务总开关关闭
 69     // kCLAuthorizationStatusAuthorized          已授权(废弃)
 70     // kCLAuthorizationStatusAuthorizedAlways    用户允许该程序无论何时都可授权
 71     // kCLAuthorizationStatusAuthorizedWhenInUse 用户同意在程序在可见时授权
 72     if (status == kCLAuthorizationStatusNotDetermined) {
 73         NSLog(@"等待用户授权");
 74     }else if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) {
 75         NSLog(@"授权成功");
 76         
 77         // 开始定位
 78         [self.manager startUpdatingLocation];
 79     } else {
 80         NSLog(@"授权失败");
 81     }
 82 }
 83 // 2.定位成功调用(调用频率非常高,所以要代码控制调用频率)
 84 // 参数:locations 位置数组(上一位置、当前位置)
 85 - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
 86 {
 87     // 1.只需获取一次用户位置信息就停止
 88     // [self.manager stopUpdatingLocation];
 89     
 90     // 2.可以在ViewDidLoad中设置定位精确度和走动范围定位
 91     // 用于导航
 92     
 93     // 3.获取最后一次地理位置信息
 94     // location.coordinate         // 坐标,包含经纬度
 95     // location.altitude           // 设置海拔高度(单位是米)
 96     // location.course             // 设置前进方向(0北/90东/180南/270西)
 97     // location.horizontalAccuracy // 水平精准度
 98     // location.verticalAccuracy   // 垂直精准度
 99     // location.speed              // 设备移动速度(单位米/秒)
100     // location.timestamp          // 定位信息返回的时间
101     CLLocation *location = [locations lastObject];
102     NSLog(@"纬度:%f, 经度:%f", location.coordinate.latitude, location.coordinate.longitude);
103 }
104 
105 @end

  实例二:定位信息计算

  1 // ViewController.h文件
  2 #import "ViewController.h"
  3 #import <CoreLocation/CoreLocation.h> // 导入头文件
  4 
  5 // 遵循定位协议<CLLocationManagerDelegate>
  6 @interface ViewController ()<CLLocationManagerDelegate>
  7 
  8 // CLLocationManager管理者对象
  9 @property (nonatomic, strong) CLLocationManager *manager;
 10 // 上一次的位置信息
 11 @property (nonatomic, strong) CLLocation *lastLocation;
 12 // 定位的总路程
 13 @property (nonatomic, assign) CLLocationDistance totalDistance;
 14 // 定位的总时间
 15 @property (nonatomic, assign) NSTimeInterval totalTime;
 16 
 17 @end
 18 
 19 @implementation ViewController
 20 
 21 #pragma mark - 懒加载
 22 // 初始化创建CoreLocation管理者
 23 - (CLLocationManager *)manager
 24 {
 25     if (_manager == nil) {
 26         _manager = [[CLLocationManager alloc] init];
 27     }
 28     return _manager;
 29 }
 30 
 31 - (void)viewDidLoad
 32 {
 33     [super viewDidLoad];
 34     
 35     // 设置代理
 36     self.manager.delegate = self;
 37     
 38     // 参数设置
 39     // a.定位精准度(越精准越耗电)
 40     self.manager.desiredAccuracy = kCLLocationAccuracyBest;
 41     // b.每隔多少米定位一次(单位:米)
 42     self.manager.distanceFilter = 5;
 43     
 44     // iOS8以上:要求手动授权
 45     if ([[UIDevice currentDevice] systemVersion].floatValue >= 8.0) {
 46         // a.请求前台和后台的定位权限
 47         [self.manager requestAlwaysAuthorization];
 48         // b.请求前台的定位权限
 49         // [self.manager requestWhenInUseAuthorization];
 50     } else {
 51         // 开始定位
 52         [self.manager startUpdatingLocation];
 53     }
 54     
 55     // iOS9:同一项目中允许多个定位对象并存,可随时代码控制某个定位对象的后台定位授权
 56     if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {
 57         // 后台授权属性:allowsBackgroundLocationUpdates(YES:允许,NO:不允许)
 58         self.manager.allowsBackgroundLocationUpdates = YES;
 59     }
 60 }
 61 
 62 #pragma mark - 协议方法<CLLocationManagerDelegate>
 63 // 1.用户授权状态一经改变就会调用
 64 - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
 65 {
 66     if (status == kCLAuthorizationStatusNotDetermined) {
 67         NSLog(@"等待用户授权");
 68     }else if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) {
 69         NSLog(@"授权成功");
 70         
 71         // 开始定位
 72         [self.manager startUpdatingLocation];
 73     } else {
 74         NSLog(@"授权失败");
 75     }
 76 }
 77 // 2.定位成功调用(调用频率非常高,所以要代码控制调用频率)
 78 // 参数:locations 位置数组(上一位置、当前位置)
 79 - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
 80 {
 81     // location.coordinate         // 坐标,包含经纬度
 82     // location.altitude           // 设置海拔高度(单位是米)
 83     // location.course             // 设置前进方向(0北/90东/180南/270西)
 84     // location.horizontalAccuracy // 水平精准度
 85     // location.verticalAccuracy   // 垂直精准度
 86     // location.speed              // 设备移动速度(单位米/秒)
 87     // location.timestamp          // 定位信息返回的时间
 88 
 89     
 90     // 现实开发中的问题
 91     // 1.获取连续的两次定位一共走啦多远?(解决:当前位置 - 上一位置)
 92     // 2.获取连续的两次定位走这段路花费多长时间?(解决:当前的时间戳 - 上一时间戳)
 93     // 3.获取连续的两次定位走这段路程的平均速度?(解决:总路程 / 总时间)
 94     // 4.累计走啦多远?(解决:每连续两次定位走的路程相加)
 95     // 5.累计定位走啦多久?(解决:每连续两次定位走的时间相加)
 96     // 6.累计的平均速度?(解决:总路程 / 总时间)
 97     
 98     // 获取当前的位置信息
 99     CLLocation *currentLocation = locations.lastObject;
100     // 判断上一次位置是否为空
101     if (self.lastLocation != nil) {
102         // 1.计算连续两次定位走的距离(米)
103         CLLocationDistance distance = [currentLocation distanceFromLocation:self.lastLocation];
104         // 2.计算连续两次定位之间的时间(秒)
105         NSTimeInterval disTime = [currentLocation.timestamp timeIntervalSinceDate:self.lastLocation.timestamp];
106         // 3.计算连续两次定位之间的平均速度(米/秒)
107         CGFloat speed = distance / disTime;
108         // 4.累加距离(米)
109         self.totalDistance += distance;
110         // 5.累加时间(秒)
111         self.totalTime += disTime;
112         // 6.计算整个的平均速度(米/秒)
113         CGFloat avgSpeed = self.totalDistance / self.totalTime;
114         
115         NSLog(@"连续两次定位走的路程:%f, 连续两次定位走的时间:%f, 连续两次定位的平均速度:%f", distance, disTime, speed);
116         NSLog(@"总路程:%f, 总时间:%f, 平均速度:%f", self.totalDistance, self.totalTime, avgSpeed);
117     }
118     // 保存当前位置信息
119     self.lastLocation = currentLocation;
120 }
121 
122 @end

  实例三:获取用户地理方向

 1 // ViewController.h文件
 2 #import "ViewController.h"
 3 #import <CoreLocation/CoreLocation.h> // 导入头文件
 4 
 5 // 遵循定位协议<CLLocationManagerDelegate>
 6 @interface ViewController ()<CLLocationManagerDelegate>
 7 
 8 // CLLocationManager管理者对象
 9 @property (nonatomic, strong) CLLocationManager *manager;
10 // 指南针图片
11 @property (nonatomic, strong) UIImageView *imageView;
12 @end
13 
14 @implementation ViewController
15 
16 #pragma mark - 懒加载
17 // 初始化创建CoreLocation管理者
18 - (CLLocationManager *)manager
19 {
20     if (_manager == nil) {
21         _manager = [[CLLocationManager alloc] init];
22     }
23     return _manager;
24 }
25 
26 - (void)viewDidLoad
27 {
28     [super viewDidLoad];
29     
30     // 1.添加指南针图片
31     _imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"bg"]];
32     _imageView.center = CGPointMake(self.view.center.x, self.view.center.y);
33     [self.view addSubview:_imageView];
34     
35     // 2.成为CoreLocation管理者的代理监听获取到的位置
36     self.manager.delegate = self;
37     
38     // 3.开始获取用户位置
39     // 注意:获取用户的方向信息是不需要用户授权的
40     [self.manager startUpdatingHeading];
41 }
42 #pragma mark - CLLocationManagerDelegate
43 // 当获取到用户方向时就会调用
44 - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
45 {
46     // 地理方向(CLHeading)
47     // newHeading.magneticHeading // 设备与磁北的相对角度(一般开发都是获取这个)
48     // newHeading.trueHeading     // 设备与真北的相对角度(必须和定位一起使用)
49 
50     // 1.将获取到的角度转为弧度 = (角度 * π) / 180;
51     CGFloat angle = newHeading.magneticHeading * M_PI / 180;
52     
53     // 2.旋转图片
54     // transform
55     // 顺时针:正弧度
56     // 逆时针:负弧度
57     // self.compasspointer.transform = CGAffineTransformIdentity; // 清空旋转弧度
58     self.imageView.transform = CGAffineTransformMakeRotation(-angle);
59 }
60 
61 @end

  实例四:检测用户区域

 1 // ViewController.h文件
 2 #import "ViewController.h"
 3 #import <CoreLocation/CoreLocation.h> // 导入头文件
 4 
 5 // 遵循定位协议<CLLocationManagerDelegate>
 6 @interface ViewController ()<CLLocationManagerDelegate>
 7 
 8 // CLLocationManager管理者对象
 9 @property (nonatomic, strong) CLLocationManager *manager;
10 
11 @end
12 
13 @implementation ViewController
14 
15 #pragma mark - 懒加载
16 // 初始化创建CoreLocation管理者
17 - (CLLocationManager *)manager
18 {
19     if (_manager == nil) {
20         _manager = [[CLLocationManager alloc] init];
21     }
22     return _manager;
23 }
24 
25 - (void)viewDidLoad
26 {
27     [super viewDidLoad];
28     
29     // 设置代理
30     self.manager.delegate = self;
31     
32     // 对于iOS8,请求用户主动授权
33     if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) {
34         [self.manager requestAlwaysAuthorization];
35     }
36     // 对于iOS9,允许动态改变后台授权状态
37     if ([[UIDevice currentDevice].systemVersion doubleValue] >= 9.0) {
38         self.manager.allowsBackgroundLocationUpdates = YES;
39     }
40     
41     // 创建区域对象
42     // CLRegion类有两个子类
43     // CLCircularRegion 地图上圆形区域
44     // CLBeaconRegion   蓝牙发射器信号区域
45     
46     // 创建圆形区域
47     // 参数1:圆心(经纬度)
48     // 参数2:半径(米)
49     // 参数3:区域ID(类似于区域标识)
50     CLLocationCoordinate2D centerCoordinate2D = CLLocationCoordinate2DMake(40.058501, 116.304171);
51     CLCircularRegion *circularRegion = [[CLCircularRegion alloc] initWithCenter:centerCoordinate2D radius:200 identifier:@"circularRegionID"];
52     
53     // 开始检测用户所在的区域
54     [self.manager startMonitoringForRegion:circularRegion];
55 }
56 
57 #pragma mark - 协议方法<CLLocationManagerDelegate>
58 // 1.用户进入监测区域,就会调用
59 - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
60 {
61     NSLog(@"用户位于指定区域内");
62 }
63 // 2.用户偏离监测区域,就会调用
64 - (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
65 {
66     NSLog(@"用户已偏离指定区域");
67 }
68 
69 @end

5.CoreLocation的地理编码

 

      

 

posted @ 2016-01-20 18:09  Frank9098  阅读(188)  评论(0)    收藏  举报