CoreLocation定位

 1 CoreLocation的基础使用

1>iOS7

    1.创建CoreLocation的管理者。CoreLocation要强引用

    2.实现CLLocationManagerDelegate代理。

    3.开始或停止代理

#import <CoreLocation/CoreLocation.h>
@interface ViewController () <CLLocationManagerDelegate>
@property (nonatomic, strong)CLLocationManager *mrg;
@end
@implementation ViewController

-(CLLocationManager *)mrg
{
    if (_mrg == nil) {
        //1,创建CoreLocation的管理者
        self.mrg = [[CLLocationManager alloc] init];
        
    }
    return _mrg;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //2,成为CoreLocation的代理
    self.mrg.delegate = self;
    
    //3,开始定位
    [self.mrg startUpdatingLocation];
    
}

#pragma mark - CLLocationManagerDelegate
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
     NSLog(@"%s",__func__);
    
    //打印位置信息
        /*
     location.coordinate; 坐标, 包含经纬度
     location.altitude; 设备海拔高度 单位是米
     location.course; 设置前进方向 0表示北 90东 180南 270西
     location.horizontalAccuracy; 水平精准度
     location.verticalAccuracy; 垂直精准度
     location.timestamp; 定位信息返回的时间
     location.speed; 设备移动速度 单位是米/秒, 适用于行车速度而不太适用于不行
     */
    CLLocation *location = [locations lastObject];
    NSLog(@"%f,%f",location.coordinate.latitude,location.coordinate.longitude);
    
    
    //  获取到位置信息之后就会调用(调用频率非常高).如果只需要获取一次, 就要在这里设置停止
    //  [self.mgr stopUpdatingLocation];
}
2>iOS8

          iOS7只要开始定位, 系统就会自动要求用户对你的应用程序授权. 但是从iOS8开始, 想要定位必须先"自己""主动"要求用户授权.在iOS8中不仅仅要主动请求授权, 而且必须再info.plist文件中配置一项属性才能弹出授权窗口,value值可以随意写.eg:iOS7也可以添加,但不强制。

            Privacy - Location Usage Description(iOS7)

            NSLocationWhenInUseDescription,允许在前台获取GPS的描述

            NSLocationAlwaysUsageDescription,允许在后台获取GPS的描述

    if([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0)
    {
        NSLog(@"是iOS8");
        // 主动要求用户对我们的程序授权, 授权状态改变就会通知代理
        [self.mgr requestAlwaysAuthorization];     // 请求前台和后台定位权限
//      [self.mgr requestWhenInUseAuthorization];  // 请求前台定位权限
    }
    
 //iOS8中需要额外添加在个代理方法
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    /*
     用户从未选择过权限
     kCLAuthorizationStatusNotDetermined
     无法使用定位服务,该状态用户无法改变
     kCLAuthorizationStatusRestricted
     用户拒绝该应用使用定位服务,或是定位服务总开关处于关闭状态
     kCLAuthorizationStatusDenied
     已经授权(废弃)
     kCLAuthorizationStatusAuthorized
     用户允许该程序无论何时都可以使用地理信息
     kCLAuthorizationStatusAuthorizedAlways
     用户同意程序在可见时使用地理位置
     kCLAuthorizationStatusAuthorizedWhenInUse
     */  
    if (status == kCLAuthorizationStatusNotDetermined) {
        NSLog(@"等待用户授权");
    }else if (status == kCLAuthorizationStatusAuthorizedAlways ||
              status == kCLAuthorizationStatusAuthorizedWhenInUse)
        
    {
        NSLog(@"授权成功");
        // 开始定位
        [self.mgr startUpdatingLocation];
        
    }else
    {
        NSLog(@"授权失败");
    }
}


2 CoreLocation的常用属性
    1.// 设置多久获取一次(单位是米,超出多米就开始调用)
    self.mgr.distanceFilter = 500;
    
    2.// 设置获取位置的精确度
    /*
      kCLLocationAccuracyBestForNavigation 最佳导航
      kCLLocationAccuracyBest;  最精准
      kCLLocationAccuracyNearestTenMeters;  10米
      kCLLocationAccuracyHundredMeters;  百米
      kCLLocationAccuracyKilometer;  千米
      kCLLocationAccuracyThreeKilometers;  3千米
     */
    self.mgr.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;


CoreLocation的常用功能 
1>导航
// 上一次的位置
@property (nonatomic, strong) CLLocation *previousLocation;
// 总路程
@property (nonatomic, assign) CLLocationDistance  sumDistance;
// 总时间
@property (nonatomic, assign) NSTimeInterval  sumTime;

#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    
    // 获取当前的位置
    CLLocation *newLocation = [locations lastObject];
    
    if (self.previousLocation != nil) {
        // 计算两次的距离(单位时米) 
        CLLocationDistance distance = [newLocation distanceFromLocation:self.previousLocation];
        // 计算两次之间的时间(单位只秒) timestamp 当前获取到为止信息的时间
        NSTimeInterval dTime = [newLocation.timestamp timeIntervalSinceDate:self.previousLocation.timestamp];
        // 计算速度(米/秒)
        CGFloat speed = distance / dTime;
        
        // 累加时间
        self.sumTime += dTime;
        
        // 累加距离
        self.sumDistance += distance;
        
        //  计算平均速度
        CGFloat avgSpeed = self.sumDistance / self.sumTime;
        
        NSLog(@"距离%f 时间%f 速度%f 平均速度%f 总路程 %f 总时间 %f", distance, dTime, speed, avgSpeed, self.sumDistance, self.sumTime);
    }
    
    // 纪录上一次的位置
    self.previousLocation = newLocation;
    
}
2>指南针
    // 1.添加指南针图片
    UIImageView *iv = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"bg_compasspointer"]];
    iv.center = CGPointMake(self.view.center.x, self.view.center.y);
    [self.view addSubview:iv];
    self.compasspointer = iv;

#pragma mark - CLLocationManagerDelegate
// 当获取到用户方向时就会调用
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
    /*
     magneticHeading 设备与磁北的相对角度;trueHeading 设置与真北的相对角度
     必须和定位一起使用, 一般使用磁北
     
     顺时针 正
     逆时针 负数
     */
    
    // 1.将获取到的角度转为弧度 = (角度 * π) / 180;
    CGFloat angle = newHeading.magneticHeading * M_PI / 180;
    // 2.旋转图片 效果不好,建议使用核心动画
    self.compasspointer.transform = CGAffineTransformMakeRotation(-angle);
}
3>区域监听
- (void)viewDidLoad {
    [super viewDidLoad];
    self.mgr.delegate = self;
    
    // 注意:如果是iOS8, 想进行区域检测, 必须自己主动请求获取用户隐私的权限.像CoreLocation的iOS8使用一样,需要在info添加权限,如NSLocationAlwaysUsageDescription
    if  ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0 )
    {
        [self.mgr requestAlwaysAuthorization];
    }
   
    // 开始检测用户所在的区域
     //1.创建区域
    /*CLRegion 有两个子类是专门用于指定区域的
    一个可以指定蓝牙的范围CLBeaconRegion/ 一个是可以指定圆形的范围CLCircularRegion
    */
    //创建圆形区域, 指定区域中心点的经纬度, 以及半径、标识
    CLLocationCoordinate2D center = CLLocationCoordinate2DMake(40.058501, 116.304171);  
    CLCircularRegion *circular = [[CLCircularRegion alloc] initWithCenter:center radius:500 identifier:@"软件园"];  
    
    //2.开始监听
    [self.mgr startMonitoringForRegion:circular];
 
}

#pragma mark - CLLocationManagerDelegate
// 进入监听区域时调用
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    NSLog(@"进入监听区域时调用");
}
// 离开监听区域时调用
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
    NSLog(@"离开监听区域时调用");
}
4>地理编码

    这个方法只需要头文件声明#import <CoreLocation/CoreLocation.h>。而与以上方法不同,是不需要实现代理,只需要简单实现编码对象的方法

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //1.创建地理编码对象
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    
    // 2.利用地理编码对象编码
    // 根据传入的地址获取该地址对应的经纬度信息
    [geocoder geocodeAddressString:@"beijing" completionHandler:^(NSArray *placemarks, NSError *error) {
        
        if (placemarks.count == 0 || error != nil) {
            return ;
        }
        
        // placemarks地标数组, 地标数组中存放着地标, 每一个地标包含了该位置的经纬度以及城市/区域/国家代码/邮编等等..。
        for (CLPlacemark  *placemark in placemarks) {
            NSLog(@"name:%@ addressDictionary:%@ latitude:%f longitude:%f",
                  placemark.name,
                  placemark.addressDictionary,
                  placemark.location.coordinate.latitude,
                  placemark.location.coordinate.longitude);
            
            
            NSArray *address = placemark.addressDictionary[@"FormattedAddressLines"];
            //遍历数组,读取插入字符串
            NSMutableString *strM = [NSMutableString string];
            for (NSString *str in address) {
                [strM appendString:str];
            }
            NSLog(@"strm:%@",strM);
            
        }
        
    }];
}
5>反地理编码

和地位编码一样,只需要简单导入头文件

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //1.创建地理编码对象
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    
    CLLocation *location = [[CLLocation alloc] initWithLatitude:23.0f longitude:112.9f];
    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
        
        for (CLPlacemark *placemark in placemarks) {
            NSLog(@"name:%@ \n addressDictionary:%@ \n latitude:%f \n longitude:%f \n locality:%@",
                  placemark.name,                           //具体位置
                  placemark.addressDictionary,              //地理位置详细信息
                  placemark.location.coordinate.latitude,   //经度
                  placemark.location.coordinate.longitude,  //纬度
                  placemark.locality);                      //城市名字
        }
    }];
}


4 第三方框架-LocationManager

同样iOS8需要在info添加权限

#import "INTULocationManager.h"

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 1.创建位置管理者
    INTULocationManager *mgr = [INTULocationManager sharedInstance];
    
    // 2.利用位置管理者获取位置
    /*
     INTULocationAccuracy 精确度,包括更新的位置和时间
     timeout              延时时间
     status               发送状态
     */
    [mgr requestLocationWithDesiredAccuracy:INTULocationAccuracyRoom  timeout:5 delayUntilAuthorized:YES block:^(CLLocation *currentLocation, INTULocationAccuracy achievedAccuracy, INTULocationStatus status) {
        if (status == INTULocationStatusSuccess) {
            NSLog(@"获取位置成功 %f %f", currentLocation.coordinate.latitude , currentLocation.coordinate.longitude);
        }else if(status ==  INTULocationStatusError)
        {
            NSLog(@"获取失败");
        }
    }];
}

003935_C7za_2346786.jpg




转载于:https://my.oschina.net/u/2346786/blog/508699

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值