最近在做项目, 遇到了一个问题就是 如何让iOS7~~iOS9的定位 .因为项目需求只是需要获取用户所在的城市, 而不用十分具体详细的精确定位, 服务端考虑用 区号 , 作为标识,但是看了百度的SDK, 不忍吐槽.最后决定用 高德 的SDK进行定位的开发.高德的定位SDK也是基于CoreLocation框架进行二次的开发, 但是其提供具体的 区号 , 十分方便与服务端进行相应的逻辑开发.如果用 原生 的, 在大陆可能存在各种各样的问题, 因为大陆的iphone手机有韩版, 日版, 欧版, 美版, 就差没非版了, 这些手机获取的定位信息会存在七七八八的非中文编码, 十分头疼.所以就采用高德的定位SDK进行统一的定位解决.
使用高德的SDK定位, 十分简单, 直接导入其框架的 主头文件
import <AMapLocationKit/AMapLocationKit.h>
.不要问我框架的主头文件是啥.接着直接使用高德的一次性定位,
[self.locationManager requestLocationWithReGeocode:YES completionBlock:^(CLLocation *location, AMapLocationReGeocode *regeocode, NSError *error) { if (!error) { } }];
在异步回调的block中就有相应的信息.如果出错error会有值, 不为空.
我们知道当用户关闭定位服务, 或者禁止本程序进行定位的时候,最后是能在App中就直接跳转到相应的设置界面进行设置.这里为了程序的兼容和响应速度, 我采用CCLocationManager这个自带的类进行判断. 为什么不使用高德的一次性定位 , 进行间接的判断, 当error有值时候,提示开启定位服务.这里主要存在的问题是因为, 高德提供的一次性定位, 的定位速度不快, 我自己用起来都觉得很慢, 所以当用户点了定位, 还用等你去做定位请求后, 再通过这个定位结果判断是否开启定位服务, 是十分不合理的.所以我的思路便是采用CCLocationManager进行精确度最低的定位.
具体的逻辑就是
2.如果定位服务开启, 则判断当前程序的定位权限是否授权.我是直接通过CCLocationManager对象的 startUpdatingLocation 方法, 让其开始定位,然后在代理方法中进行判断,如果定位权限是开启的就会回调
locationManager:didUpdateLocations:
否则回调的是
locationManager:didFailWithError:
而当回调了didUpdateLocations时候我们就可以断定,定位服务是开启的,并且定位权限已经授权给应用程序, 则可以调用高德的SDK开始定位, 或者跳转到响应控制器中进行定位和具体的业务处理.
当然了, 不管是调用了上面哪个的代理方法, 都用调用 定位管理器 的 stopUpdatingLocation , 停止定位.因为我们只是需要知道这个信息, 不需要再继续定位.
在程序中关于定位我做了两重的优化.或者说是缓存.
第一级缓存:一进入应用程序后, 如果定位服务是开启的, 则开一个优先级最高的线程进行高德的一次定位.如果定位成功, 则将缓存中的定位信息清空, 写入新的定位信息.
第二季缓存:在经过响应的控制器进行定位之前, 先从一级缓存中取到定位信息.如果有定位信息, 则不再进行高德的一次性定位, 如果没有定位信息, 则继续进行高德的一次性定位, 如果定位成功, 将定位信息写入缓存.
经过这样的优化, 定位服务是十分快速的~具体工程代码不披露了.涉及到公司的业务.大概的技术思路就是这样.
后续会用空,我会封装适用于国内的一个定位的第三方框架.上传到github, 敬请关注