iOS定位-CoreLocation 记录

备注:本教程只考虑iOS 8.0+,测试切勿忘了权限

iOS开发中CoreLocation是一个与定位有关的类,本教程将利用CoreLocation来实现三个小功能,获取经纬度、区域位置监听、地理位置编码。


1.获取经纬度

//
//  LocationController.m
//  CoreLocation
//
//  Created by LouKit on 2017/2/17.
//  Copyright © 2017年 LouKit. All rights reserved.
//

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

@interface LocationController ()<CLLocationManagerDelegate>

@property (nonatomic,strong) CLLocationManager *locMgr;
@property (nonatomic, strong) CLLocation *lastLoc;

@end

@implementation LocationController


-(CLLocationManager *)locMgr{

    if(![CLLocationManager locationServicesEnabled]){
    
        NSLog(@"定位服务没有开启不可用");
        return nil;
    }
    if (!_locMgr) {
        _locMgr = [[CLLocationManager alloc]init];
        _locMgr.delegate = self;
        
        //ios9 以上才有
        //_locMgr.allowsBackgroundLocationUpdates = YES;
        
        //前台定位
        //[_locMgr requestWhenInUseAuthorization];
        
        //前后台定位
        [_locMgr requestAlwaysAuthorization];
        
        //一些属性设置
        //定位精度
        /**
        kCLLocationAccuracyBestForNavigation
        CLLocationAccuracy kCLLocationAccuracyBest;
        CLLocationAccuracy kCLLocationAccuracyNearestTenMeters;
        CLLocationAccuracy kCLLocationAccuracyHundredMeters;
        CLLocationAccuracy kCLLocationAccuracyKilometer;
        CLLocationAccuracy kCLLocationAccuracyThreeKilometers;
        **/
        _locMgr.desiredAccuracy = kCLLocationAccuracyBest;
        //定位频率
        _locMgr.distanceFilter = 100;//每隔100米定位一次
    }
    return _locMgr;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor yellowColor];
    
    // 开始定位用户的位置
    if([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied){
        //doing
    }else{
        //一次定位
        //[self.locMgr requestLocation];
        [self.locMgr startUpdatingLocation];
    }
    
    [self countLineDistance];
    
}




#pragma mark - CLLocationManagerDelegate

//当前位置授权状态的改变
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{

    /**
    用户未决定
    kCLAuthorizationStatusNotDetermined = 0,
    //受限制
    kCLAuthorizationStatusRestricted,

    //拒绝
    kCLAuthorizationStatusDenied,

    //前后台定位授权
    kCLAuthorizationStatusAuthorizedAlways NS_ENUM_AVAILABLE(10_12, 8_0),
    //前台定位
    kCLAuthorizationStatusAuthorizedWhenInUse NS_ENUM_AVAILABLE(NA, 8_0),
    **/
}

//定位到位置时调用 (调用频率特别高)
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{

    CLLocation *loc = [locations firstObject];
    CLLocationCoordinate2D coordinate = loc.coordinate;
    NSLog(@"经纬度:------%f %f", coordinate.latitude, coordinate.longitude);
    /**
     altitude : 海拔
     horizontalAccuracy : 如果是负值, 代表当前位置数据不可用
     verticalAccuracy : 海拔  -- 如果是负值, 代表当前海拔数据不可用
     course : 航向 (0.0----359.9)
     speed : 速度
     floor  : 楼层
     方法:
     distanceFromLocation : 计算两个坐标之间的物理直线距离
     */
    
    /
    //    >场景演示:打印当前用户的行走方向,偏离角度以及对应的行走距离,
    //    例如:”北偏东 30度 方向,移动了  8米”
    if (loc.horizontalAccuracy < 0) {
        return;
    }
    // 1. 确定当前航向
    NSInteger index = (int)loc.course / 90;
    
    NSArray *courseStrArray = @[@"北偏东", @"东偏南", @"南偏西", @"西偏北"];
    
    NSString *courseStr = courseStrArray[index];
    
    
    // 2. 确定偏离角度
    NSInteger angle = (int)loc.course % 90;
    
    // 代表是正方向
    if (angle == 0) {
        courseStr = [@"正" stringByAppendingString:[courseStr substringToIndex:1]];
    }
    
    
    // 3. 确定行走距离
    CGFloat  distance = 0;
    if (_lastLoc) {
        distance = [loc distanceFromLocation:_lastLoc];
    }
    _lastLoc = loc;
    
    
    // 4. 打印
    NSString *noticeStr;
    if(angle != 0)
    {
        noticeStr = [NSString stringWithFormat:@"%@ %zd 度方向, 移动了 %f米", courseStr, angle, distance];
    }else
    {
        noticeStr = [NSString stringWithFormat:@"%@ 方向, 移动了 %f米", courseStr, distance];
    }
    
    
    NSLog(@"%@", noticeStr);
    
    
    // 停止定位
//    [self.locMgr stopUpdatingLocation];
}

//定位失败时调用
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    NSLog(@"%s",__func__);
}


//计算两个经纬度之间的直线距离
- (void)countLineDistance
{
    // 计算2个经纬度之间的直线距离
    CLLocation *loc1 = [[CLLocation alloc] initWithLatitude:40 longitude:120];
    CLLocation *loc2 = [[CLLocation alloc] initWithLatitude:41 longitude:120];
    CLLocationDistance distance = [loc1 distanceFromLocation:loc2];
    NSLog(@"countLineDistance:%f", distance);
}

@end

2.区域位置监听
//
//  RegionController.m
//  CoreLocation
//
//  Created by LouKit on 2017/2/17.
//  Copyright © 2017年 LouKit. All rights reserved.
//

#import "RegionController.h"

#import <CoreLocation/CoreLocation.h>

@interface RegionController ()<CLLocationManagerDelegate>

@property (nonatomic,strong) CLLocationManager *locMgr;
@property (nonatomic, strong) CLLocation *lastLoc;

@end

@implementation RegionController


-(CLLocationManager *)locMgr{
    
    if(![CLLocationManager locationServicesEnabled]){
        
        NSLog(@"定位服务没有开启不可用");
        return nil;
    }
    if (!_locMgr) {
        _locMgr = [[CLLocationManager alloc]init];
        _locMgr.delegate = self;
        //前后台定位
        [_locMgr requestAlwaysAuthorization];
    
    }
    return _locMgr;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor yellowColor];
    
    // 判断当前设备是否支持区域监听(区域类型)
    if (![CLLocationManager isMonitoringAvailableForClass:[CLCircularRegion class]]) {
        return;
    }
    
    // 创建区域
    CLLocationCoordinate2D center = CLLocationCoordinate2DMake(37.78,-122.40);//测试时在模拟器外部需要设置好经纬度
    CLLocationDistance distance = 1000.0;
    if(distance > self.locMgr.maximumRegionMonitoringDistance)
    {
        distance = self.locMgr.maximumRegionMonitoringDistance;
    }
    CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:center radius:distance identifier:@"lk_identifier"];
    
    // 监听一个区域(只有用户有进入区域, 或者离开区域时才会调用代理)
    [self.locMgr startMonitoringForRegion:region];
    

    // 请求某个区域的状态
    // 获取到指定区域的状态, 而且当状态发生变化时也会调用对应的代理方法
    [self.locMgr requestStateForRegion:region];
}




#pragma mark - CLLocationManagerDelegate

/**
 *  当前请求指定区域状态时, 回调的代理方法
 *  @param manager 位置管理者
 *  @param state   状态
 *  @param region  区域
 */
-(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region{

    //state
    //CLRegionStateUnknown, // 不知道
    //CLRegionStateInside, // 在区域内部
    //CLRegionStateOutside // 在区域外部
    
    if(state == CLRegionStateInside)
    {
         NSLog(@"区域内部");
    }else if (state == CLRegionStateOutside)
    {
         NSLog(@"区域外部");
    }
    
    NSLog(@"%s;%@",__func__,region.identifier);
}
/**
 *  进入指定区域时调用
 *
 *  @param manager 位置管理者
 *  @param region  区域
 */
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{

    NSLog(@"%s;%@",__func__,region.identifier);
}

/**
 *  离开指定区域时调用
 *
 *  @param manager 位置管理者
 *  @param region  区域
 */
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region{

    NSLog(@"%s;%@",__func__,region.identifier);
}

@end

3.地理位置编码
//
//  GeocoderController.m
//  CoreLocation
//
//  Created by LouKit on 2017/2/17.
//  Copyright © 2017年 LouKit. All rights reserved.
//

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

@interface GeocoderController ()

@property (nonatomic,strong) CLGeocoder *geocoder;

@end

@implementation GeocoderController


-(CLGeocoder *)geocoder{

    if (!_geocoder) {
        _geocoder = [[CLGeocoder alloc]init];
    }
    return _geocoder;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor yellowColor];
    
    //[self geocode];
    [self reverseGeocode];
}

//地理编码
-(void)geocode{

    [self.geocoder geocodeAddressString:@"北京" completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        if (error) {
            NSLog(@"输入的地址有误");
            return ;
        }
        //取出最前面地址
        CLPlacemark *pm  = [placemarks firstObject];
        
        NSLog(@"lat:%f;lon:%f;addressDictionary:%@",pm.location.coordinate.latitude,pm.location.coordinate.longitude,pm.addressDictionary);
        
        /**
        lat:39.904989;lon:116.405285;addressDictionary:{
        City = Beijing;
        Country = China;
        CountryCode = CN;
        FormattedAddressLines =     (
                                     "Beijing China"
                                     );
        Name = Beijing;
        State = Beijing;
         }**/

    }];
}

//反地理编码
-(void)reverseGeocode{
    
    CLLocation *location = [[CLLocation alloc] initWithLatitude:39.904989 longitude:116.405285];
    
    [self.geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        if (error) {
            NSLog(@"输入的地址有误");
            return ;
        }
        //取出最前面地址
        CLPlacemark *pm  = [placemarks firstObject];
        
        NSLog(@"reverseGeocode CLPlacemark:%@",pm.addressDictionary);
        /**
        CLPlacemark:{
        City = Beijing;
        Country = China;
        CountryCode = CN;
        FormattedAddressLines =     (
                                     "East Chang'an Avenue No.14 Dongcheng",
                                     "Beijing China"
                                     );
        Name = "Ministry of Public Security";
        State = Beijing;
        Street = "East Chang'an Avenue No.14";
        SubLocality = Dongcheng;
        Thoroughfare = "East Chang'an Avenue No.14";
       }**/
        
    }];


}
@end



。。。。比较懒不想写文字,而且写这就是当个笔记用

因此一些概念性以及CoreLocation中一些基础方法、代理方面了解可以
参考 Kenshin Cui's Blog iOS开发系列--地图与定位

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值