1.地图的简介
在移动互联网时代,移动app能解决用户的很多生活琐事,比如
导航:去任意陌生的地方
周边:找餐馆、找酒店、找银行、找电影院
手机软件:微信摇一摇、QQ附近的人、微博、支付宝等
在上述应用中,都用到了地图和定位功能,在iOS开发中,要想加入这两大功能,必须基于两个框架进行开发
Map Kit :用于地图展示
Core Location :用于地理定位
地图定位(CoreLocation框架,地理编码与反地理编码)
地图显示(MapKit框架)
自定义大头针
2.地图的定位
1 CLLocationManager的常用操作 2 // 开始用户定位 3 - (void)startUpdatingLocation; 4 // 停止用户定位 5 - (void) stopUpdatingLocation; 6 7 // 当调用了startUpdatingLocation方法后,就开始不断地定位用户的位置,中途会频繁地调用下面的代理方法 8 - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations; 9 // 参数locations中的元素对象是CLLocation对象
1 // 每隔多少米定位一次 2 @property(assign, nonatomic) CLLocationDistance distanceFilter; 3 4 // 定位精确度(越精确就越耗电) 5 @property(assign, nonatomic) CLLocationAccuracy desiredAccuracy; 6 7 CLLocationAccuracy 是一个枚举值 8 /* 9 最佳导航 10 kCLLocationAccuracyBestForNavigation 11 最精准 12 kCLLocationAccuracyBest; 13 10米 14 kCLLocationAccuracyNearestTenMeters; 15 百米 16 kCLLocationAccuracyHundredMeters; 17 千米 18 kCLLocationAccuracyKilometer; 19 3千米 20 kCLLocationAccuracyThreeKilometers; 21 */ 22 23 实现定位只需要下面几步: 24 1. 创建管理者对象 25 self.manager = [[CLLocationManager alloc] init]; 26 2. 设置代理 27 self.manager.delegate = self; 28 3. 开启定位 29 [self.manager startUpdatingLocation]; 30 注意:从iOS 7之后,苹果在保护用户隐私方面做了很大的加强,以下操作都必须经过用户批准授权: 31 ①要想获得用户的位置和访问用户的通讯录、日历、相机、相册等等都需要用户来手动授权。 32 ②当想访问用户的隐私信息时,系统会自动弹出一个对话框让用户授权 33 34 4 、请求授权 (授权方式根据实际情况进行选择) 35 36 // 请求授权 37 38 [self.manager requestAlwaysAuthorization]; // 请求前台和后台定位 39 40 [self.manager requestWhenInUseAuthorization]; // 请求后台定位 定位服务授权状态,返回枚举类型:kCLAuthorizationStatusNotDetermined: 用户尚未做出决定是否启用定位服务kCLAuthorizationStatusRestricted: 没有获得用户授权使用定位服务,可能用户没有自己禁止访问授权kCLAuthorizationStatusDenied :用户已经明确禁止应用使用定位服务或者当前系统定位服务处于关闭状态kCLAuthorizationStatusAuthorizedAlways: 应用获得授权可以一直使用定位服务,即使应用不在使用状态kCLAuthorizationStatusAuthorizedWhenInUse: 使用此应用过程中允许访问定位服务
用户隐私的保护
NSLocationWhenInUseUsageDescription(当打开APP应用的时候会触发这个方法)
NSLocationAlwaysUsageDescription(总是处于打开的状态)
模拟位置:(如果是模拟器,需要设置模拟位置(经纬度))======点击模拟器---->Debug---->Location----->CustomLocation更改经纬度
北京的经纬度是:北纬40°,东经116°
大连的经纬度是:北纬39°,东经121°
郑州的经纬度是:北纬34°,东经113°
上海的经纬度是:北纬31°,东经121°
广州的经纬度是:北纬23°,东经113°
西安的经纬度是:北纬34°,东经108°
使用CLGeocoder可以完成"地理编码"和"反地理编码"
地理编码:根据给定的地名,获得具体的位置信息(比如经纬度、地址的全称等)
反地理编码:根据给定的经纬度,获得具体的位置信息
1 // 地理编码方法 2 - (void)geocodeAddressString:(NSString *)addressString completionHandler:(CLGeocodeCompletionHandler)completionHandler; 3 4 // 反地理编码方法 5 - (void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler;
1 当地理编码/反地理编码完成时,就会调用CLGeocodeCompletionHandler 2 typedef void (^CLGeocodeCompletionHandler)(NSArray *placemarks, NSError *error); 3 4 block包含2个参数 5 error:当编码出错时(比如编码不出具体的信息),2其错误信息会包含在error中 6 placemarks:里面装着CLPlacemark对象 7 8 CLPlacemark的字面意思是地标,封装详细的地址位置信息 9 10 // 地理位置 11 @property (nonatomic, readonly) CLLocation *location; 12 13 // 区域 14 @property (nonatomic, readonly) CLRegion *region; 15 16 // 详细的地址信息 17 @property (nonatomic, readonly) NSDictionary *addressDictionary; 18 19 // 地址名称 20 @property (nonatomic, readonly) NSString *name; 21 22 // 地点名称 23 @property (nonatomic, readonly) NSString *locality;
总结:
CLLocationManager 定位的基础信息
CLLocation 某个位置的地理信息
CLLocationCoordinate2D 存放经纬度的结构体
CLGeocoder 地理位置编码与反编码的类
CLPlacemark 地标.
1 #import "ViewController.h" 2 // 第一步: 引入库的头文件 3 #import <CoreLocation/CoreLocation.h> 4 5 @interface ViewController ()<CLLocationManagerDelegate> 6 7 // 定位管理器 8 // CoreLocation框架中的CLLocationManager用于管理定位的管理器 9 // CoreLocation框架中的CLGeocoder能进行编码和反编码 10 @property (nonatomic, strong) CLLocationManager *manager; 11 12 // 编码反编码的类 13 @property (nonatomic, strong) CLGeocoder *geocoder; 14 15 16 @end 17 18 @implementation ViewController 19 20 - (void)viewDidLoad { 21 [super viewDidLoad]; 22 // Do any additional setup after loading the view, typically from a nib. 23 // 定位步骤 24 // 第一步: 初始化定位管理器 25 self.manager = [[CLLocationManager alloc] init]; 26 // 第二步: 进行隐私的判断并授权 27 // 如何跳转隐私界面 28 // 进行隐私的判断 29 if (![CLLocationManager locationServicesEnabled]) { 30 NSLog(@"是否前往隐私进行设置允许定位"); 31 } 32 33 // 根据状态进行授权 34 // 进行版本的判断 35 if ([[[UIDevice currentDevice] systemVersion] integerValue] >= 8.0) { 36 37 if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedWhenInUse) { 38 39 /* 40 定位服务授权状态,返回枚举类型: 41 kCLAuthorizationStatusNotDetermined: 用户尚未做出决定是否启用定位服务 42 kCLAuthorizationStatusRestricted: 没有获得用户授权使用定位服务,可能用户没有自己禁止访问授权 43 kCLAuthorizationStatusDenied :用户已经明确禁止应用使用定位服务或者当前系统定位服务处于关闭状态 44 kCLAuthorizationStatusAuthorizedAlways: 应用获得授权可以一直使用定位服务,即使应用不在使用状态 45 kCLAuthorizationStatusAuthorizedWhenInUse: 使用此应用过程中允许访问定位服务 46 47 */ 48 49 50 // 在授权请求之前需要在info.plist中设置允许定位的内容:NSLocationWhenInUseUsageDescription NSLocationAlwaysUsageDescription 51 // 请求授权 52 [self.manager requestWhenInUseAuthorization]; 53 } 54 } 55 // 第三步: 设置管理器的代理和相关属性 56 self.manager.delegate = self; 57 // 设置经度 58 self.manager.desiredAccuracy = 100; 59 // 设置最小更新距离 60 self.manager.distanceFilter = 100; 61 // 第四步: 开启定位 62 [self.manager startUpdatingLocation]; 63 64 //====================编码和反编码===========================\ 65 66 // 初始化编码和反编码对象 67 self.geocoder = [[CLGeocoder alloc] init]; 68 69 // 根据地名获取经纬度 70 [self getCoordinateByAddress:@"平安村"]; 71 72 // 根据经纬度反编码取出地名 73 [self getAddressByLongitude:113 Latitude:34]; 74 75 // 计算两点之间的距离 76 [self distence]; 77 78 } 79 80 #pragma mark - 计算两个地方的距离 81 82 - (void)distence 83 { 84 // 创建位置1北京 85 CLLocation *locationBJ = [[CLLocation alloc] initWithLatitude:40 longitude:116]; 86 // 位置2大连 87 CLLocation *locationDL = [[CLLocation alloc] initWithLatitude:39 longitude:121]; 88 CLLocationDistance distance = [locationBJ distanceFromLocation:locationDL]; 89 NSLog(@"北京到大连的距离:%f", distance); 90 91 } 92 93 #pragma mark - 根据经纬度获取地名 94 - (void)getAddressByLongitude:(CLLocationDegrees)longitude Latitude:(CLLocationDegrees)latitude 95 { 96 // 反编码 97 // 创建CLLocation 98 CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude]; 99 //反编码 100 [_geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) { 101 102 NSDictionary *dic = placemarks.firstObject.addressDictionary; 103 104 NSLog(@"反编码地理位置信息:%@", dic); 105 }]; 106 } 107 108 109 #pragma mark - 根据地名获取相关的信息 110 - (void)getCoordinateByAddress:(NSString *)address 111 { 112 // 编码方法 113 [_geocoder geocodeAddressString:address completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) { 114 115 // 根据返回的地标,取出第一个位置(地标的位置很多) 116 CLPlacemark *mark = placemarks.firstObject; 117 // 根据地标得到location 118 CLLocation *location = mark.location; 119 // 根据location获取区域 120 CLRegion *region = mark.region; 121 // 获取字典信息 122 NSDictionary *addressDictionary = mark.addressDictionary; 123 124 NSLog(@"地标位置:%@,区域:%@,地理位置信息:%@",location,region,addressDictionary); 125 126 127 // NSString *name=placemark.name;//地名 128 // NSString *thoroughfare=placemark.thoroughfare;//街道 129 // NSString *subThoroughfare=placemark.subThoroughfare; //街道相关信息,例如门牌等 130 // NSString *locality=placemark.locality; // 城市 131 // NSString *subLocality=placemark.subLocality; // 城市相关信息,例如标志性建筑 132 // NSString *administrativeArea=placemark.administrativeArea; // 州 133 // NSString *subAdministrativeArea=placemark.subAdministrativeArea; //其他行政区域信息 134 // NSString *postalCode=placemark.postalCode; //邮编 135 // NSString *ISOcountryCode=placemark.ISOcountryCode; //国家编码 136 // NSString *country=placemark.country; //国家 137 // NSString *inlandWater=placemark.inlandWater; //水源、湖泊 138 // NSString *ocean=placemark.ocean; // 海洋 139 // NSArray *areasOfInterest=placemark.areasOfInterest; //关联的或利益相关的地标 140 141 }]; 142 } 143 144 #pragma mark - CLLocationManagerDelegate的代理方法 145 // 这个代理方法是定位成功之后开始更新位置信息,只要移动设置的最小距离之后也开始走这个方法 146 - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations 147 { 148 // 获取最后一次的位置 149 CLLocation *location = locations.lastObject; 150 // 获取位置坐标 151 CLLocationCoordinate2D coordinate = location.coordinate; 152 // latitude(纬度) longitude(经度) altitude(海拔) course(航线) speed(速度) 153 NSLog(@"%f,%f, %f, %f,%f",coordinate.latitude,coordinate.longitude,location.altitude,location.course,location.speed); 154 /* 155 注意: 156 157 1.定位频率和定位精度并不应当越精确越好,需要视实际情况而定,因为越精确越耗性能,也就越费电。 158 159 2.定位成功后会根据设置情况频繁调用-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations方法,这个方法返回一组地理位置对象数组,每个元素一个CLLocation代表地理位置信息(包含经度、纬度、海报、行走速度等信息),之所以返回数组是因为有些时候一个位置点可能包含多个位置。 160 161 3.使用完定位服务后如果不需要实时监控应该立即关闭定位服务以节省资源。 162 163 4.除了提供定位功能,CLLocationManager还可以调用startMonitoringForRegion:方法对指定区域进行监控。 164 */ 165 166 // 为了节省电源,如果不适用定位,需要把定位关掉 167 [self.manager stopUpdatingLocation]; 168 169 } 170 171 // 定位失败 172 - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error 173 { 174 NSLog(@"定位失败"); 175 }