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.h>

第二种方式:

只需导入头文件即可,前提是代码中使用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];

}

到此定位完成。

运行会弹出如图:


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进入后台就不再定位,如果要实现前后台定位的话,必须手动设置后台模式。如图


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;

城市

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


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

code:



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

一、创建单例工具类

YWZLocationTools.h

YWZLocationTools.m

YWZLocationTools.h中的代码 

YWZLocationTools.m中的代码


在ViewController里使用工具类

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容