iOS 定位和地图

简介:

在移动互联网时代,移动app能解决用户的很多生活琐事,比如周边:找餐馆、找KTV、找电影院等等

导航:根据用户设定的起点和终点,进行路线规划,并指引用户如何到达。

在上述应用中,都用到了定位和地图功能,在iOS开发中,要想加入这2大功能,必须基于2个框架进行开发:

CoreLocation:用于地理定位,如:地理编码,区域监听等(着重功能实现)

MapKit:用于地图展示,例如大头针,路线、覆盖层展示等(着重界面展示)

2个专业术语:

LBS:location Based Service (基于位置的服务)

ScLoMo:Social Local Mobile (索罗门)


定位

CoreLocation:用于地理定位,地理编码,区域监听等(着重功能实现)

地理编码:将某个位置转换为经纬度,如:北京天安门->100.333445 , 22.88888

反地理编码:将某个位置的经纬度转换为文字描述的具体位置,如:100.333445 , 22.88888  ->北京天安门

区域监听:监听某个位置是否在某个区域。

CoreLocation的使用

第一种方式:

导入框架 :CoreLocation.frameWork

导入头文件:#import

第二种方式:

只需导入头文件即可,前提是代码中使用CoreLocation框架中的某一个类创建的对象,他就会在链接的过程中隐式的把对应的框架链接进来。

经验:CoreLocation框架中所有的类型数据的前缀都是以CL开头。

CoreLocation框架中使用CLLocationManager对象来做定位服务。

iOS8.0之前的定位实现:

1、创建位置管理者:

_manager = [[CLLocationManager alloc] init];

2、设置代理:通过代理来获取位置信息等,遵守代理协议。

_manager.delegate = self;

3、开始定位:startUpdatingLocation调用此方法开始定位,会不断的获取用户的位置信息

[self.manager startUpdatingLocation];

4、实现代理方法:获取用户的位置信息等。

*只要获取到用户的位置的时候就会调用(很频繁)

*  @param manager位置管理者

*  @param locations位置数组 ,位置信息等,都在数字的最后一个元素

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

{

               NSLog(@"%@",locations);

               CLLocation*location = [locationslastObject];

}

到此定位完成。

运行会弹出如图:


iOS 定位和地图_第1张图片

PS:从iOS6开始,苹果在保护用户隐私方面做了很大的加强,只要是要想获得用户的位置、想访问用户的通讯录、日历、相机、相册等操作,都必须经过用户批准授权,开发者可以在Info.plist中设置NSLocationUsageDescription说明定位的目的.

如何判断授权状态?

通过代理方法didChangeAuthorizationStatus:

*当授权状态发生改变时调用

*  @param manager位置管理者

*  @param status当前授权状态 有五种状态

- (void)locationManager:(CLLocationManager*)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status

{

          switch(status) {

          case  kCLAuthorizationStatusNotDetermined:

                   NSLog(@"用户未决定");

                   break;

          case  kCLAuthorizationStatusRestricted:

                   NSLog(@"受限制");

                   break;

          case  kCLAuthorizationStatusDenied:

                   //判断当前设备是否支持定位,并且定位是否开启

                   if([CLLocationManager  locationServicesEnabled])

                   {

                              NSLog(@"定位开启,但是被拒绝");

                             // ios8.0之前需要截图提醒引导用户,如何接受授权。

                             // iOS8.0之后只需要调用系统只带的API就会自动跳转到设置界面。

                    }else{

                              NSLog(@"定位未开启");

                    }

                    break;

           case  kCLAuthorizationStatusAuthorizedAlways:

                    NSLog(@"前后台");

                    break;

          case  kCLAuthorizationStatusAuthorizedWhenInUse:

                   NSLog(@"前台");

                   break;

          default:

                   break;

      }

}

其他属性设置

- (void)stopUpdatingLocation :停止定位(针对一次性定位,比如定位到用户位置之后就停止),可以在上面的代理方法中使用。

distanceFilter:每隔多远定位一次,比如:_manager.distanceFilter=10;代表每隔10米定位一次。

desiredAccuracy:定位的精确度(越精确,越耗电)。它的取值比较多有6种,如下

kCLLocationAccuracyBestForNavigation //最适合导航

kCLLocationAccuracyBest; //最好的

kCLLocationAccuracyNearestTenMeters;//附近10米

kCLLocationAccuracyHundredMeters;//附近100米

kCLLocationAccuracyKilometer;//附近1000米

kCLLocationAccuracyThreeKilometers;//附近3000米

- (CLLocationDistance)distanceFromLocation:(constCLLocation*)location方法可以计算2个位置之间的距离

coordinate:经纬度

altitude:海拔

course:路线,航向(取值范围是0.0°~359.9°,0.0°代表真北方向)

speed:移动速度(单位是m/s)

horizontalAccuracy如果是负数,代表当前位置不可用

PS:目前的定位只是前台定位,APP进入后台就不再定位,如果要实现前后台定位的话,必须手动设置后台模式。如图


iOS 定位和地图_第2张图片

iOS8.0之后的定位实现

把以上代码再跑到iOS8.0+的时候,并没有弹出授权提示框,这是因为从iOS8.0开始,苹果进一步加强了对用户隐私的保护,当APP想访问用户的隐私信息时,系统不再自动弹出一个对话框让用户授权。

解决方案:调用iOS8.0的API,主动请求用户授权

- (void)requestAlwaysAuthorization//请求允许在前后台都能获取用户位置的授权

- (void)requestWhenInUseAuthorization//请求允许在前台获取用户位置的授权

以上二选一。

务必在info.plist文件中配置对应的键值,否则以上请求授权的方法不生效

NSLocationAlwaysUsageDescription:允许在前后台获取GPS的描述

NSLocationWhenInUseDescription:允许在前台获取GPS的描述

以上二选一,和上面的调用方法要保持一直。

if([UIDevice currentDevice].systemVersion.floatValue >= 8.0) {

           [_managerrequestAlwaysAuthorization];

}

iOS9.0之后的定位实现

iOS9.0如果当前处于前台授权状态,默认是不可以后台获取用户位置。但可以设置以下属性为YES,就可以继续获取后台位置,但是会出现蓝条;

if([UIDevice currentDevice].systemVersion.floatValue >= 8.0) {

            [_managerrequestAlwaysAuthorization];

            if([UIDevicecurrentDevice].systemVersion.floatValue>=9.0)

           {

                       _manager.allowsBackgroundLocationUpdates=YES;

            }

}

PS:iOS9.0可以单次请求用户位置

- (void)requestLocation注意:此方法不能与startUpdatingLocation一起使用。

-(void)locationManager:(nonnullCLLocationManager*)managerdidUpdateLocations:(nonnullNSArray *)locations//成功调用

-(void)locationManager:(nonnullCLLocationManager*)managerdidFailWithError:(nonnullNSError*)error//失败调用


地理编码:CLGeocoder

使用CLGeocoder可以完成“地理编码”和“反地理编码”。

地理编码方法

- (void)geocodeAddressString:(NSString*)addressString  completionHandler:(CLGeocodeCompletionHandler)completionHandler;

反地理编码方法

- (void)reverseGeocodeLocation:(CLLocation*)location  completionHandler:(CLGeocodeCompletionHandler)completionHandler;

CLGeocodeCompletionHandler

当地理\反地理编码完成时,就会调用CLGeocodeCompletionHandler

typedefvoid(^CLGeocodeCompletionHandler)(NSArray*placemarks,NSError*error);

这个block传递2个参数

error:当编码出错时(比如编码不出具体的信息)有值

placemarks:里面装着CLPlacemark对象

CLPlacemark

CLPlacemark的字面意思是地标,封装详细的地址位置信息

@property(nonatomic,readonly)CLLocation*location;

地理位置

@property(nonatomic,readonly)CLRegion*region;

区域

@property(nonatomic,readonly)NSDictionary*addressDictionary;

详细的地址信息

@property(nonatomic,readonly)NSString*name;

地址名称

@property(nonatomic,readonly)NSString*locality;

城市

地理编码案例:输入经纬度,点击地理编码按钮,可得到详细地址;输入详细地址,点击反地理编码按钮,可得到相应的经纬度。如图:


iOS 定位和地图_第3张图片

首先在storyboard布局好界面,连好线。

code:

iOS 定位和地图_第4张图片


iOS 定位和地图_第5张图片


iOS 定位和地图_第6张图片

案例:封装简单定位工具类(代理模式转block模式),获取用户位置,通过blcok回调返回用户位置信息。

一、创建单例工具类

YWZLocationTools.h

YWZLocationTools.m

YWZLocationTools.h中的代码 

iOS 定位和地图_第7张图片

YWZLocationTools.m中的代码

iOS 定位和地图_第8张图片
iOS 定位和地图_第9张图片
iOS 定位和地图_第10张图片


iOS 定位和地图_第11张图片
iOS 定位和地图_第12张图片
iOS 定位和地图_第13张图片

在ViewController里使用工具类

iOS 定位和地图_第14张图片

你可能感兴趣的:(iOS 定位和地图)