iOS 地图

IOS地图定位导航

2016-04-18  本文已影响1073人  袁俊亮技术博客

title : IOS地图定位导航
category : UI


地图定位导航

标签(空格分隔): IOS


概述

IOS中通过CoreLocation框架进行定位操作

在IOS开发中,定位地图两个功能是基于CoreLocationMapKit这两个框架来开发

CoreLocation框架的使用

CLLocationManager的常用操作

// 开始更新用户位置
- (void)startUpdatingLocation;

// 停止更新用户位置
- (void)stopUpdatingLocation;

// 当调用了startUpdatingLocation方法后,就开始不断地请求、刷新用户的位置,一旦请求到用户位置就会调用代理的以下方法
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations;

1 类方法

+ (BOOL)locationServicesEnabled;/* 返回用户是否启用定位服务 */
+ (CLAuthorizationStatus)authorizationStatus;/* 定位服务授权状态,返回枚举类型 */

typedef NS_ENUM(int, CLAuthorizationStatus){
    kCLAuthorizationStatusNotDetermined = 0, /* 用户尚未决定是否启用定位服务 */
    kCLAuthorizationStatusRestricted, /* 没有获得用户授权 */
    kCLAuthorizationStatusDenied, /* 用户禁止使用定位或者定位服务处于关闭状态 */
    kCLAuthorizationStatusAuthorizedAlways, /* 前台、后台定位授权 */
    kCLAuthorizationStatusAuthorizedWhenInUse, /* 前台定位授权 */
};

2 对象属性

// 每隔多少米定位一次
locationMgr.distanceFilter = 100;

// 定位的精确度
locationMgr.desiredAccuracy = kCLLocationAccuracyHundredMeters;

精确度枚举值(越精确就越耗电)

 kCLLocationAccuracyBestForNavigation /* 最适合导航的 */
 kCLLocationAccuracyBest; /* 精度最好的 */
 kCLLocationAccuracyNearestTenMeters; /* 附近10米 */
 kCLLocationAccuracyHundredMeters; /* 附近100米 */
 kCLLocationAccuracyKilometer; /* 附近1000米 */
 kCLLocationAccuracyThreeKilometers; /* 附近3000米 */

3 对象方法

#pragma mark - 定位追踪
-(void)startUpdatingLocation;/* 开始定位追踪 */
-(void)stopUpdatingLocation;/* 停止定位追踪 */
#pragma mark - 导航追踪
-(void)startUpdatingHeading;/* 开始导航方向追踪 */
-(void)stopUpdatingHeading;/* 停止导航方向追踪 */
#pragma mark - 区域定位追踪
-(void)startMonitoringForRegion:(CLRegion *)region;/* 开始对某个区域进行定位追踪 */
-(void)stopMonitoringForRegion:(CLRegion *)region;/* 停止对某个区域进行定位追踪 */
#pragma mark - 授权请求
-(void)requestWhenInUseAuthorization;/* 请求获得应用前台定位授权 */
-(void)requestAlwaysAuthorization;/* 请求获得应用前后台定位授权 */

4. 常用代理方法<CLLocationManagerDelegate>

/* 位置发生改变后调用,第一次定位也会调用 */
-(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;
/* 当用户授权状态发生变化时调用 */
-(void)locationManager:(CLLocationManager *)manager 
       didChangeAuthorizationStatus:(CLAuthorizationStatus)status;

CoreLocation定位功能的使用步骤

#import <CoreLocation/CoreLocation.h>

IOS8.0之前的定位使用

1.1 前台定位
- (void)viewDidLoad{
    [super viewDidLoad];
    if (![CLLocationManager locationServicesEnabled]) {
        NSLog(@"定位服务当前可能尚未打开,请设置打开!");
        return;
    }
    [self initLocationManager];
    //调用方法,开始更新用户位置信息
    [self.locationM startUpdatingLocation];
}
//创建CLLocationManager并启动定位
- (void)initLocationManager{
    //创建CLLocationManager对象并设置代理
    self.locationM = [[CLLocationManager alloc] init];
    self.locationM.delegate = self;
    //设置定位精度和位置更新最小距离
    self.locationM.distanceFilter = 100;
    self.locationM.desiredAccuracy = kCLLocationAccuracyBest;
}
//在对应的代理方法中获取位置信息
- (void)locationManager:(CLLocationManager *)manager 
     didUpdateLocations:(NSArray<CLLocation*> *)locations
{
    CLLocation *location = [locations firstObject];//取出第一个位置
    /* 
        使用位置前, 务必判断当前获取的位置是否有效
        如果水平精确度小于零, 代表虽然可以获取位置对象, 但是数据错误, 不可用
     */
    if (location.horizontalAccuracy < 0)
        return;
    CLLocationCoordinate2D coordinate = location.coordinate;//位置坐标 
    CGFloat longitude = coordinate.longitude;//经度
    CGFloat latitude = coordinate.latitude;//纬度
    CGFloat altitude = location.altitude;//海拔
    CGFloat course = location.course;//方向
    CGFloat speed = location.speed;//速度
    NSLog(@"经度:%f,纬度:%f",longitude,latitude);   
    NSLog(@"海拔:%f,方向:%f,速度:%f",altitude,course,speed);
    //如果不需要实时定位,使用完即使关闭定位服务
    [self.locationM stopUpdatingLocation];   
}
  • 1 定位频率和定位精度并不是越精确越好,需要视实际情况而定,因为越精确越耗性能,也就越费电。
  • 2 定位成功后会根据设置情况频繁调用locationManager:didUpdateLocations:方法
  • 3 每个元素一个CLLocation代表地理位置信息,之所以返回数组是因为有些时候一个位置点可能包含多个位置。
  • 4 使用完定位服务后,如果不需要实时监控应该立即关闭定位服务,以节省资源。
  • 5 除了提供定位功能,还可以调用startMonitoringForRegion:方法对指定区域进行监控。
1.2 后台定位

在前台的基础上,在项目的Capabilities中的Background Modes打开,并勾选上Location updates。这样就可以开启后台定位模式了

开启后台定位模式.png

2 IOS8.0之后

IOS8.0开始,苹果进一步加强了对用户隐私的保护。当APP想访问用户的隐私信息是,系统不再自动弹出一个对话框让用户授权

解决方案:

调用IOS8.0的API,主动请求用户授权

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

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

注意务必需要在Info.plist文件中配置以下对应的键值,否则以上请求授权的方法不会生效。

NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription
- (void)viewDidLoad{
    [super viewDidLoad];
    if (![CLLocationManager locationServicesEnabled]) {
        NSLog(@"定位服务当前可能尚未打开,请设置打开!");
        return;
    }
    [self initLocationManager];
    //如果没有授权,则请求用户授权
    CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
    if (status == kCLAuthorizationStatusNotDetermined){
        //请求前台定位授权
        //[self.locationM requestWhenInUseAuthorization];
        //请求前后台定位授权
        [self.locationM requestAlwaysAuthorization];
    }
}

//创建CLLocationManager并启动定位
- (void)initLocationManager{
    //创建CLLocationManager对象并设置代理
    self.locationM = [[CLLocationManager alloc] init];
    self.locationM.delegate = self;
    //设置定位精度和位置更新最小距离
    self.locationM.distanceFilter = 100;
    self.locationM.desiredAccuracy = kCLLocationAccuracyBest;
}
// 当用户授权状态发生变化时调用
- (void)locationManager:(CLLocationManager *)manager 
        didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    switch (status) {
        case kCLAuthorizationStatusNotDetermined://用户还未决定
        {
            NSLog(@"用户还未决定");
            break;
        }
        case kCLAuthorizationStatusRestricted://访问受限
        {
            NSLog(@"访问受限");
            break;
        }
        case kCLAuthorizationStatusDenied://定位关闭时或用户APP授权为永不授权时调用
        {
            NSLog(@"定位关闭或者用户未授权");
            if ([CLLocationManager locationServicesEnabled]) {
    NSLog(@"定位开启,但被拒");
}else{
    NSLog(@"定位关闭,不可用");
}
            break;
        }
        case kCLAuthorizationStatusAuthorizedAlways://获取前后台定位授权
        {
            NSLog(@"获取前后台定位授权");
            [self.locationM startUpdatingLocation];
            break;
        }
        case kCLAuthorizationStatusAuthorizedWhenInUse://获得前台定位授权
        {
            NSLog(@"获得前台定位授权");
            [self.locationM startUpdatingLocation];
            break;
        }
        default:break;
    }
}
//在对应的代理方法中获取位置信息
- (void)locationManager:(CLLocationManager *)manager 
     didUpdateLocations:(NSArray<CLLocation*> *)locations
{
    CLLocation *location = [locations firstObject];//取出第一个位置
    /* 
        使用位置前, 务必判断当前获取的位置是否有效
        如果水平精确度小于零, 代表虽然可以获取位置对象, 但是数据错误, 不可用
     */
    if (location.horizontalAccuracy < 0)
        return;
    CLLocationCoordinate2D coordinate = location.coordinate;//位置坐标
    CGFloat longitude = coordinate.longitude;//经度
    CGFloat latitude = coordinate.latitude;//纬度
    CGFloat altitude = location.altitude;//海拔
    CGFloat course = location.course;//方向
    CGFloat speed = location.speed;//速度
    NSLog(@"经度:%f,纬度:%f",longitude,latitude);
    NSLog(@"海拔:%f,方向:%f,速度:%f",altitude,course,speed);
    //如果不需要实时定位,使用完即使关闭定位服务
    [self.locationM stopUpdatingLocation];
}

注意对于IOS8.0以后的提示请求访问用户地理位置的提示需要进行系统适配

// 系统适配
if ([self.locationMgr respondsToSelector:@selector(requestAlwaysAuthorization)]) {
    [self.locationMgr requestAlwaysAuthorization];
}

if ([[UIDevice currentDevice].systemVersion doubleValue]>8.0) {
    // 设置前后台授权定位
    [self.locationMgr requestAlwaysAuthorization];
    // 设置前台授权
    [self.locationMgr requestWhenInUseAuthorization];
}

if ([self.locationMgr respondsToSelector:@selector(allowsBackgroundLocationUpdates)]) {
    // 在IOS9.0以后,需要允许后台获取用户位置
    // 注意,这里同时需要勾选后台模式
    self.locationMgr.allowsBackgroundLocationUpdates = YES;
}

参考资料:
iOS8中使用CoreLocation定位

上一篇下一篇

猜你喜欢

热点阅读