一:定位功能
基本概念:
CLLocationManager:定位管理器类。
CLLocationManagerDelegate:该协议代表定位管理器的delegate协议,实现该协议的对象可负责处理CLLocationManager的定位事件。
CLLocation:该对象代表位置。该对象包含了当前设备的精度,维度,高度,速度,路线等信息,还包含了该定位信息的水平精确度,垂直精确度以及时间戳信息。
CLHeading:代表设备的移动方向。
CLRegion:该对象代表一个区域,一般程序不会直接使用该类,而是使用它的两个子类,即CLCircularRegion(圆形区域)和CLBeaconRegion(蓝牙信号区)。
除此之外,CoreLocation框架还涉及一个CLLocationCoordinate2D结构体变量,该结构体变量包含精度,维度两个值。其中CLLocation对象的coordinate属性就是一个CLLocationCoordinate2D的结构体变量。
注意:为了在iOS应用中使用CoreLocation.framework,需要完成两件事:1)为应用添加CoreLocation.framework框架,2)在需要使用到定位服务及相关类的源文件中倒入对应头文件#import <CoreLocation/CoreLocation.h>。
二:获取位置信息
使用CoreLocation.framework框架进行定位只需要3步即可。
1)创建CLLocationManager对象,该对象负责获取定位的相关信息,并为该对象设置一些必要的属性。
2)为CLLocationManager指定delegate属性,该属性必须是一个实现CLLocationManagerDelegate协议的对象。实现CLLocationManagerDelegate协议时可根据需要实现协议中的方法。
3)调用CLLocationManager的startUpdatingLocation方法获取定位信息,定位结束时,可调用stopUpdatingLocation。
定位是一个很常用的功能,如一些地图软件打开之后如果用户允许软件定位的话,那么打开软件后就会自动锁定到当前位置,如果用户手机移动那么当前位置也会跟随着变化。要实现这个功能需要使用Core Loaction中CLLocationManager类,首先看一下这个类的一些主要方法和属性:
+ (BOOL)locationServicesEnabled;//是否启用定位服务,通常如果用户没有启用定位服务可以提示用户打开定位服务;
+ (BOOL)headingAvailable;//返回该设备是否支持磁力计算方向
+ (BOOL)isRangingAvailable;//返回蓝牙信号范围服务是否可用。
+ (BOOL)significantLocationChangeMonitoringAvailable;//返回返回重大位置改变监听是否可用。
+ (BOOL)deferredLocationUpdatesAvailable;//返回延迟定位更新是否可用。
+ (CLAuthorizationStatus)authorizationStatus;
//定位服务授权状态,返回枚举类型:
typedefNS_ENUM(int, CLAuthorizationStatus) {
kCLAuthorizationStatusNotDetermined://用户尚未做出决定是否启用定位服务
kCLAuthorizationStatusRestricted://没有获得用户授权使用定位服务,可能用户没有自己禁止访问授权
kCLAuthorizationStatusDenied://用户已经明确禁止应用使用定位服务或者当前系统定位服务处于关闭状态
kCLAuthorizationStatusAuthorizedAlways://应用获得授权可以一直使用定位服务,即使应用不在使用状态
kCLAuthorizationStatusAuthorizedWhenInUse://使用此应用过程中允许访问定位服务
};
- (void)startUpdatingLocation;//开始定位追踪,开始定位后将按照用户设置的更新频率执行-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations;方法反馈定位信息
- (void)stopUpdatingLocation;//停止定位追踪
- (void)startUpdatingHeading;//开始导航方向追踪
- (void)stopUpdatingHeading;//停止导航方向追踪
- (void)stopMonitoringForRegion:(CLRegion *)region;//开始对某个区域进行定位追踪,开始对某个区域进行定位后。如果用户进入或者走出某个区域会调用- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region和- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region代理方法反馈相关信息
- (void)stopMonitoringForRegion:(CLRegion *)region;//停止对某个区域进行定位追踪
- (void)requestWhenInUseAuthorization;//请求获得应用使用时的定位服务授权,注意使用此方法前在要在info.plist中配置NSLocationWhenInUseUsageDescription
- (void)requestAlwaysAuthorization;//请求获得应用一直使用定位服务授权,注意使用此方法前要在info.plist中配置NSLocationAlwaysUsageDescription
// 设置定位精度
@property(assign, nonatomic) CLLocationAccuracy desiredAccuracy;
//定位精度类型如下:
externconstCLLocationAccuracy kCLLocationAccuracyBestForNavigation//用于导航定位
externconstCLLocationAccuracy kCLLocationAccuracyBest;//最精确定位
externconstCLLocationAccuracy kCLLocationAccuracyNearestTenMeters;//十米误差范围
externconstCLLocationAccuracy kCLLocationAccuracyHundredMeters;//百米误差范围
externconstCLLocationAccuracy kCLLocationAccuracyKilometer;//千米误差范围
externconstCLLocationAccuracy kCLLocationAccuracyThreeKilometers;//三千米误差范围
//位置信息更新最小距离,只有移动大于这个距离才更新位置信息,默认为kCLDistanceFilterNone:不进行距离限制
@property(assign, nonatomic) CLLocationDistance distanceFilter;
//部分代理方法如下
-(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要求始终能在后台开启定位服务,iOS8不仅会在首次打开 App时主动向你询问,还会在日常使用中弹窗提醒你该 App一直在后台使用定位服务,并询问你是否继续允许。在iOS7及以前的版本,如果在应用程序中使用定位服务只要在程序中调用startUpdatingLocation方法应用就会询问用户是否允许此应用是否允许使用定位服务,同时在提示过程中可以通过在info.plist中配置通过配置Privacy - Location Usage Description告诉用户使用的目的,同时这个配置是可选的。
但是在iOS8中配置配置项发生了变化,可以通过配置NSLocationAlwaysUsageDescription或者NSLocationWhenInUseUsageDescription来告诉用户使用定位服务的目的,并且注意这个配置是必须的,如果不进行配置则默认情况下应用无法使用定位服务,打开应用不会给出打开定位服务的提示,除非安装后自己设置此应用的定位服务。同时,在应用程序中需要根据配置对requestAlwaysAuthorization或locationServicesEnabled方法进行请求。由于本人机器已经更新到最新的iOS8.2下面的内容主要针对iOS8,使用iOS7的朋友需要稍作调整。操作图片如下:
注意:
1.定位频率和定位精度并不应当越精确越好,需要视实际情况而定,因为越精确越耗性能,也就越费电。
2.定位成功后会根据设置情况频繁调用-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations方法,这个方法返回一组地理位置对象数组,每个元素一个CLLocation代表地理位置信息(包含经度、纬度、海报、行走速度等信息),之所以返回数组是因为有些时候一个位置点可能包含多个位置。
3.使用完定位服务后如果不需要实时监控应该立即关闭定位服务以节省资源。
4.除了提供定位功能,CLLocationManager还可以调用startMonitoringForRegion:方法对指定区域进行监控。
CLLocation类中常用的部分属性:
@property(readonly, nonatomic) CLLocationCoordinate2D coordinate;//CLLocationCoordinate2D结构体变量,包含精度和维度信息
@property(readonly, nonatomic) CLLocationDistance altitude;//当前设备的海拔高度
@property(readonly, nonatomic) CLLocationAccuracy horizontalAccuracy;//水平精确度
@property(readonly, nonatomic) CLLocationAccuracy verticalAccuracy;//垂直精确度
@property(readonly, nonatomic) CLLocationSpeed speed;//设备的移动速度
@property(readonly, nonatomic, copy) NSDate *timestamp;//定位信息的返回日期
@property(readonly, nonatomic) CLLocationDirection course;//表示当前设备前进的方向,值为0,表示向北,90度表示向东,180度表示向南,270度表示向西。
#import <UIKit/UIKit.h>
@interfaceFKViewController: UIViewController
@property (strong,nonatomic)IBOutletUITextField *longitudeTxt;
@property (strong,nonatomic)IBOutletUITextField *latitudeTxt;
@property (strong,nonatomic)IBOutletUITextField *altitudeTxt;
@property (strong,nonatomic)IBOutletUITextField *speedTxt;
@property (strong,nonatomic)IBOutletUITextField *courseTxt;
- (IBAction)bnTapped:(id)sender;
@end
#import <CoreLocation/CoreLocation.h>
#import "FKViewController.h"
@interface FKViewController () <CLLocationManagerDelegate>
@property (strong,nonatomic)CLLocationManager *locationManager;
@end
@implementation FKViewController
- (void)viewDidLoad
{
[superviewDidLoad];
//创建CLLocationManager对象
self.locationManager = [[CLLocationManageralloc]init];
//如果定位服务可用。
1)定位服务只会定位一次
2)iOS8和以后要进行需要手动调用CLLocationManager对象的requestAlwaysAuthorization方法。调用该方法需要在Info.plist中设 置NSLocationAlwaysUsageDescription的值,这个值会显示在系统提示框中,值可以为空。
if (![CLLocationManagerlocationServicesEnabled]) {
NSLog(@"定位服务当前可能尚未打开,请设置打开!");
return;
}
//如果没有授权则请求用户授权
if ([CLLocationManagerauthorizationStatus]==kCLAuthorizationStatusNotDetermined){
// [_locationManager requestWhenInUseAuthorization];//必须配合使用,2种方式都可以。
// [CLLocationManager authorizationStatus]==kCLAuthorizationStatusAuthorizedWhenInUse
[_locationManagerrequestAlwaysAuthorization];
}
}
- (IBAction)bnTapped:(id)sender
{
if([CLLocationManagerauthorizationStatus]==kCLAuthorizationStatusAuthorizedWhenInUse||[CLLocationManagerauthorizationStatus]==kCLAuthorizationStatusAuthorizedAlways){
//设置代理
_locationManager.delegate=self;
//设置定位精度
_locationManager.desiredAccuracy=kCLLocationAccuracyBest;
//定位频率,每隔多少米定位一次.如果使用其他定位精确度,那么只有移动了对应的距离才会进行定位。
//CLLocationDistance distance=10.0;//十米定位一次
//_locationManager.distanceFilter=distance;
//kCLLocationAccuracyBest 时时定位,最精确.但是最终还是根据需求确定。
_locationManager.distanceFilter=kCLLocationAccuracyBest;
//启动跟踪定位。
[_locationManagerstartUpdatingLocation];
}
}
// 成功获取定位数据后将会激发该方法.当设置成最高精确度时,此方法被时时调用
-(void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
{
//获取最后一个定位数据
CLLocation* location = [locationslastObject];
//依次获取CLLocation中封装的经度、纬度、高度、速度、方向等信息。
self.latitudeTxt.text = [NSStringstringWithFormat:@"%g",
location.coordinate.latitude];
self.longitudeTxt.text = [NSStringstringWithFormat:@"%g",
location.coordinate.longitude];
self.altitudeTxt.text = [NSStringstringWithFormat:@"%g",
location.altitude];
self.speedTxt.text = [NSStringstringWithFormat:@"%g",
location.speed];
NSLog(@"~~~~%g" , location.speed);
self.courseTxt.text = [NSStringstringWithFormat:@"%g",
location.course];
}
// 定位失败时激发的方法
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
NSLog(@"定位失败: %@",error);
}
@end
代码效果图:
一进入界面,提示用户是否需要定位 定位结果显示相应的数据