CoreLocation 的基本使用 以及定位 指南针的实现 (附加: 系统版本适配的方法,和后台更新用户位置的方法及注意)

#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>

@interface ViewController ()<CLLocationManagerDelegate>

@property(nonatomic ,strong)CLLocationManager * manager;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //设置定位管理者
    CLLocationManager * manager = [[CLLocationManager  alloc]init];
    
    self.manager = manager;
    
    //设置代理
    manager.delegate = self;
    
    /* 
      kCLLocationAccuracyBestForNavigation (适合导航)
      kCLLocationAccuracyBest; (最好的)
      kCLLocationAccuracyNearestTenMeters; 附近10m
      kCLLocationAccuracyHundredMeters;  100m
      kCLLocationAccuracyKilometer;  1000m
      kCLLocationAccuracyThreeKilometers;  3000m
     */
    
    
    //设置定位精度  越进准, 越耗电,定位时间越长
    self.manager.desiredAccuracy = kCLLocationAccuracyBest;
    
    
    //每个多少米定位一次
    
//    self.manager.distanceFilter = 100;
    
    
    //获取当前设备的系统等级
    //第一种进行系统版本适配的方法
     if( [[UIDevice currentDevice].systemVersion floatValue] >= 8.0){
  
        //iOS8.0 之后 需要请求用户授权, 并在info 里配置对应的key
        
        //前后台定位授权
        [manager requestAlwaysAuthorization];
        
        //前台定位授权
//            [manager requestWhenInUseAuthorization];
        
    }
    
    //在iOS9.0 提供的下面的方法, 前提是一定要后台模式下勾选允许更新位置,否则报错
    
    //第二种进行系统版本适配的方法
    if ([self.manager respondsToSelector:@selector(allowsBackgroundLocationUpdates)]) {
        
        
        self.manager.allowsBackgroundLocationUpdates = YES;
        
    }
    
    
    [self test];
}


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    //manager默认只在前台允许更新位置,如果需要后台更新位置, 需要在后台模式中勾选 location updates
    [self.manager startUpdatingLocation];
    
    
    /*
     kCLLocationAccuracyBestForNavigation (适合导航)
     kCLLocationAccuracyBest; (最好的)
     kCLLocationAccuracyNearestTenMeters; 附近10m
     kCLLocationAccuracyHundredMeters;  100m
     kCLLocationAccuracyKilometer;  1000m
     kCLLocationAccuracyThreeKilometers;  3000m
     */
    //该方法的它会根据精确度由低到高去定位, 如果定位超时,就会直接通过代理返回当前精度的位置
//    [self.manager requestLocation];
    //这个方法需要代理实现locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
    
    //并且这个方法不能与startUpdatingLocation 和 allowDeferredLocationUpdates 同时使用
    

    
}


//当定位成功后,更新位置就会调用
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
    
    CLLocation * loc = [locations firstObject];
    
    NSLog(@"%f , %f " , loc.coordinate.latitude , loc.coordinate.longitude);
    
}

//当授权状态发生改变是调用
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
    
}

//定位失败时执行
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
    
}





//计算两个地点的距离 两个点的直线距离.(不是真实距离)
-(void)test {
    
    //创建两个地点
    CLLocation * loc1 = [[CLLocation alloc]initWithLatitude:10 longitude:119];
    
    CLLocation * loc2 = [[CLLocation alloc]initWithLatitude:10 longitude:120];
    
    //计算两个地点的距离
       CLLocationDistance dis = [loc1 distanceFromLocation:loc2];
    NSLog(@"%f" , dis);
    
    
}

//指南针的实现
-(void)test2 {
    
     CLLocationManager * manager = [[CLLocationManager alloc]init];
    
    manager.delegate = self;
    
    //开始更新指向
    [manager startUpdatingHeading];
    
}

//当指向发生改变时调用  (注意 更新指向,不用获取用户授权, 因为只是更新手机的方向,不涉及用户隐私)
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading{
    
    //磁北方向
    CLLocationDirection magneticHeading = newHeading.magneticHeading;
    
     //将角度装换为弧度
    CGFloat angel = magneticHeading/180 * M_PI ;
    
    //然后根据弧度 更改指南针图片的transform 注意是取弧度的负值,因为得到的磁北角度是相对磁北的角度,然后需要指南针旋转到磁北,所以是负值
    
}
原文地址:https://www.cnblogs.com/yuwei0911/p/5433392.html