一、配置

  1. 导入库CoreLocation.

    2.info.plist配置key NSLocationWhenInUseUsageDescription和NSLocationAlwaysUsageDescription(至少一个), 如果不设置key, 系统会忽略定位请求.

    如果需要后台定位的话需要打开后台模式.

二、使用
1.导入头文件 <CoreLocation/CoreLocation.h>.
2.创建位置管理者 CLLocationManager, 设置管理者的一些属性.
3.设置代理、遵守协议、实现代理方法.
4.调用打开地理位置方法requestWhenInUseAuthorization或requestAlwaysAuthorization, 不然当授权状态为未决定的时候不会请求用户授权.
5.调用开始更新位置方法.

导入头文件和初始化

#import <CoreLocation/CoreLocation.h>

@interface CouponWebController ()<CLLocationManagerDelegate>

// 原生地图
@property (nonatomic, strong) CLLocationManager *locService;

@end

@implementation CouponWebController

#pragma mark ----- 入口

- (void)initLocation {
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_async(queue, ^{ //让定位管理者同步执行,在主线程中创建
        // 初始化定位
    
    _locService = [[CLLocationManager alloc] init]; //创建位置管理者 CLLocationManager
    _locService.delegate = self;
    _locService.distanceFilter = 10; //设置定位距离过滤参数 (当本次定位和上次定位之间的距离大于或等于这个值时,调用代理方法)
    _locService.desiredAccuracy = kCLLocationAccuracyBest; // 设置定位精度(精度越高越耗电)
    });
    
}

开启定位

#pragma mark ----- 获取gps

- (void)getGps {
    
    [_locService requestWhenInUseAuthorization]; //调用打开地理位置方法
    [_locService startUpdatingLocation]; //调用开始更新位置方法
}

定位的相关代理方法

#pragma mark ----- CLLocationManagerDelegate

/** 获取到新的位置信息时调用*/
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
    
     [_locService stopUpdatingLocation]; //停止定位

    CLLocation *newLocation = locations.lastObject;
    NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
    if (locationAge > 1.0){ //didUpdateLocations方法可能会执行多次. 此条件限制如果已经调用一次,不再执行
        // 限制如果已经调用一次,不再执行的另一方法为:
        // 使用dispatch_once, 可以简化代码并且彻底保证线程安全,开发者无需担心加锁或同步。此外,dispatch_once更高效,它没有使用重量级的同步机制,若是那样做的话,每次运行代码前都要获取锁。相反,此函数采用“原子访问”来查询标记,以判断其所对应的代码原来是否已经执行过。在64位Mac OS X上测试,dispatch_once的执行速度要比stopUpdatingLocation快一倍。
        return;
    }else{
        NSString *longitude = [NSString stringWithFormat:@"%f",newLocation.coordinate.longitude];
        NSString *latitude = [NSString stringWithFormat:@"%f",newLocation.coordinate.latitude];
        BBLog(@"latitude = %@ longitude = %@",_latitude, _longitude); //NSLog
        
        //创建地理位置解码编码器对象 解析具体位置(如城市, 街道等)
        CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
        [geoCoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
            
            for (CLPlacemark * place in placemarks) {
                
                BBLog(@"城市:%@",place.locality);
            }
        }];
    }
}

/** 定位状态改变后会调用这个代理方法*/
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
    // kCLAuthorizationStatusDenied 定位服务没开
    if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusAuthorizedAlways) { //如果由未定位变成已定位并回到前台, 重新定位
        [_locService startUpdatingLocation];
    }
    // 定位的各种状态
    switch (status) {
        case kCLAuthorizationStatusNotDetermined:
        {
            NSLog(@"用户还未决定授权");
            break;
        }
        case kCLAuthorizationStatusRestricted:
        {
            NSLog(@"访问受限");
            break;
        }
        case kCLAuthorizationStatusDenied:
        {
            // 类方法,判断是否开启定位服务
            if ([CLLocationManager locationServicesEnabled]) {
                NSLog(@"定位服务开启,被拒绝");
            } else {
                NSLog(@"定位服务关闭,不可用");
            }
            break;
        }
        case kCLAuthorizationStatusAuthorizedAlways:
        {
            NSLog(@"获得前后台授权");
            break;
        }
        case kCLAuthorizationStatusAuthorizedWhenInUse:
        {
            NSLog(@"获得前台授权");
            break;
        }
        default:
            break;
    }
}


/** 获取位置信息失败时调用*/
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    // Alert弹框
     [CommonTool tub:YES delegate:self title:@"提示" message:@"需要开启定位权限后才可正常使用" cancelText:@"取消" sureText:@"去开启" tag:1344];
}

@end