现在很多社交、电商、团购应用都引入了地图和定位功能,似乎地图功能不再是地图应用和导航应用所特有的。的确,有了地图和定位功能确实让我们的生活更加丰富多彩,极大的改变了我们的生活方式。例如你到了一个陌生的地方想要查找附近的酒店、超市等就可以打开软件搜索周边;类似的,还有很多团购软件可以根据你所在的位置自动为你推荐某些商品。总之,目前地图和定位功能已经大量引入到应用开发中。今天就和大家一起看一下iOS如何进行地图和定位开发。
要实现地图、导航功能,往往需要先熟悉定位功能,在iOS中通过Core Location框架进行定位操作。Core Location自身可以单独使用,和地图开发框架MapKit完全是独立的,但是往往地图开发要配合定位框架使用。在Core Location中主要包含了定位、地理编码(包括反编码)功能。
定位是一个很常用的功能,如一些地图软件打开之后如果用户允许软件定位的话,那么打开软件后就会自动锁定到当前位置,如果用户手机移动那么当前位置也会跟随着变化。要实现这个功能需要使用Core Loaction中CLLocationManager类,首先看一下这个类的一些主要方法和属性:
类方法 | 说明 |
+ (BOOL)locationServicesEnabled; | 是否启用定位服务,通常如果用户没有启用定位服务可以提示用户打开定位服务 |
+ (CLAuthorizationStatus)authorizationStatus; | 定位服务授权状态,返回枚举类型: kCLAuthorizationStatusNotDetermined: 用户尚未做出决定是否启用定位服务 kCLAuthorizationStatusRestricted: 没有获得用户授权使用定位服务,可能用户没有自己禁止访问授权 kCLAuthorizationStatusDenied :用户已经明确禁止应用使用定位服务或者当前系统定位服务处于关闭状态 kCLAuthorizationStatusAuthorizedAlways: 应用获得授权可以一直使用定位服务,即使应用不在使用状态 kCLAuthorizationStatusAuthorizedWhenInUse: 使用此应用过程中允许访问定位服务 |
属性 | 说明 |
desiredAccuracy | 定位精度,枚举类型: kCLLocationAccuracyBest:最精确定位 |
distanceFilter | 位置信息更新最小距离,只有移动大于这个距离才更新位置信息,默认为kCLDistanceFilterNone:不进行距离限制 |
对象方法 | 说明 |
startUpdatingLocation | 开始定位追踪,开始定位后将按照用户设置的更新频率执行-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations;方法反馈定位信息 |
stopUpdatingLocation | 停止定位追踪 |
startUpdatingHeading | 开始导航方向追踪 |
stopUpdatingHeading | 停止导航方向追踪 |
startMonitoringForRegion: | 开始对某个区域进行定位追踪,开始对某个区域进行定位后。如果用户进入或者走出某个区域会调用- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region和- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region代理方法反馈相关信息 |
stopMonitoringForRegion: | 停止对某个区域进行定位追踪 |
requestWhenInUseAuthorization | 请求获得应用使用时的定位服务授权,注意使用此方法前在要在info.plist中配置NSLocationWhenInUseUsageDescription |
requestAlwaysAuthorization | 请求获得应用一直使用定位服务授权,注意使用此方法前要在info.plist中配置NSLocationAlwaysUsageDescription |
代理方法 | 说明 |
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations; | 位置发生改变后执行(第一次定位到某个位置之后也会执行) |
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading; |
导航方向发生变化后执行 |
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region |
进入某个区域之后执行 |
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region |
走出某个区域之后执行 |
iOS 8 还提供了更加人性化的定位服务选项。App 的定位服务不再仅仅是关闭或打开,现在,定位服务的启用提供了三个选项,「永不」「使用应用程序期间」和「始终」。同时,考虑到能耗问题,如果一款 App 要求始终能在后台开启定位服务,iOS 8 不仅会在首次打开 App 时主动向你询问,还会在日常使用中弹窗提醒你该 App 一直在后台使用定位服务,并询问你是否继续允许。在iOS7及以前的版本,如果在应用程序中使用定位服务只要在程序中调用startUpdatingLocation方法应用就会询问用户是否允许此应用是否允许使用定位服务,同时在提示过程中可以通过在info.plist中配置通过配置Privacy - Location Usage Description告诉用户使用的目的,同时这个配置是可选的。
但是在iOS8中配置配置项发生了变化,可以通过配置NSLocationAlwaysUsageDescription或者NSLocationWhenInUseUsageDescription来告诉用户使用定位服务的目的,并且注意这个配置是必须的,如果不进行配置则默认情况下应用无法使用定位服务,打开应用不会给出打开定位服务的提示,除非安装后自己设置此应用的定位服务。同时,在应用程序中需要根据配置对requestAlwaysAuthorization或locationServicesEnabled方法进行请求。由于本人机器已经更新到最新的iOS8.1下面的内容主要针对iOS8,使用iOS7的朋友需要稍作调整。
// // KCMainViewController.m // CoreLocation // // Created by Kenshin Cui on 14-03-27. // Copyright (c) 2014年 Kenshin Cui. All rights reserved. // #import "KCMainViewController.h" #import <CoreLocation/CoreLocation.h> @interface KCMainViewController ()<CLLocationManagerDelegate>{ CLLocationManager *_locationManager; } @end @implementation KCMainViewController - (void)viewDidLoad { [super viewDidLoad]; //定位管理器 _locationManager=[[CLLocationManager alloc]init]; if (![CLLocationManager locationServicesEnabled]) { NSLog(@"定位服务当前可能尚未打开,请设置打开!"); return; } //如果没有授权则请求用户授权 if ([CLLocationManager authorizationStatus]==kCLAuthorizationStatusNotDetermined){ [_locationManager requestWhenInUseAuthorization]; }else if([CLLocationManager authorizationStatus]==kCLAuthorizationStatusAuthorizedWhenInUse){ //设置代理 _locationManager.delegate=self; //设置定位精度 _locationManager.desiredAccuracy=kCLLocationAccuracyBest; //定位频率,每隔多少米定位一次 CLLocationDistance distance=10.0;//十米定位一次 _locationManager.distanceFilter=distance; //启动跟踪定位 [_locationManager startUpdatingLocation]; } } #pragma mark - CoreLocation 代理 #pragma mark 跟踪定位代理方法,每次位置发生变化即会执行(只要定位到相应位置) //可以通过模拟器设置一个虚拟位置,否则在模拟器中无法调用此方法 -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ CLLocation *location=[locations firstObject];//取出第一个位置 CLLocationCoordinate2D coordinate=location.coordinate;//位置坐标 NSLog(@"经度:%f,纬度:%f,海拔:%f,航向:%f,行走速度:%f",coordinate.longitude,coordinate.latitude,location.altitude,location.course,location.speed); //如果不需要实时定位,使用完即使关闭定位服务 [_locationManager stopUpdatingLocation]; } @end
注意:
1.定位频率和定位精度并不应当越精确越好,需要视实际情况而定,因为越精确越耗性能,也就越费电。
2.定位成功后会根据设置情况频繁调用-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations方法,这个方法返回一组地理位置对象数组,每个元素一个CLLocation代表地理位置信息(包含经度、纬度、海报、行走速度等信息),之所以返回数组是因为有些时候一个位置点可能包含多个位置。
3.使用完定位服务后如果不需要实时监控应该立即关闭定位服务以节省资源。
4.除了提供定位功能,CLLocationManager还可以调用startMonitoringForRegion:方法对指定区域进行监控。