zoukankan      html  css  js  c++  java
  • iOS学习笔记19-地图(一)定位CoreLocation

    一、定位介绍

    现在很多社交、电商、团购应用都引入了地图和定位功能,似乎地图功能不再是地图应用和导航应用所特有的。的确,有了地图和定位功能确实让我们的生活更加丰富多彩,极大的改变了我们的生活方式。要实现地图、导航功能,往往需要先熟悉定位功能

    在iOS中通过CoreLocation框架进行定位操作。

    CoreLocation自身可以单独使用,和地图开发框架MapKit完全是独立的,但是往往地图开发要配合定位框架使用。

    CoreLocation可以实现的功能:
    1. 定位功能
    2. 地理编码与逆地理编码

    二、定位核心类

    定位是一个很常用的功能,如一些地图软件打开之后如果用户允许软件定位的话,那么打开软件后就会自动锁定到当前位置,如果用户手机移动那么当前位置也会跟随着变化。要实现这个功能需要使用CoreLoactionCLLocationManager类,下面是这个类的使用说明:

    1. 类方法:
    + (BOOL)locationServicesEnabled;/* 返回用户是否启用定位服务 */
    + (CLAuthorizationStatus)authorizationStatus;/* 定位服务授权状态,返回枚举类型 */
    
    typedef NS_ENUM(int, CLAuthorizationStatus){
        kCLAuthorizationStatusNotDetermined = 0, /* 用户尚未决定是否启用定位服务 */
        kCLAuthorizationStatusRestricted, /* 没有获得用户授权 */
        kCLAuthorizationStatusDenied, /* 用户禁止使用定位或者定位服务处于关闭状态 */
        kCLAuthorizationStatusAuthorizedAlways, /* 前台、后台定位授权 */
        kCLAuthorizationStatusAuthorizedWhenInUse, /* 前台定位授权 */
    };
    
    2. 对象属性:
    • 定位精度desiredAccuracy
      枚举类型:
    • 位置信息更新最小距离distanceFilter
      浮点数,默认为kCLDistanceFilterNone,表示不进行距离限制
    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>
    
    iOS版本不同,使用也有一些区别,主要区分为:
    1. iOS8.0之前的定位使用
    2. iOS8.0之后的定位使用
    1. 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 后台定位:

    在前台的基础上,勾选后台模式Location updates

    2. iOS8之后的定位使用
    iOS8开始,需要请求定位授权:
    • 前台授权:
      在Info.plist文件中配置 NSLocationWhenInUseUsageDescriptionYES
    • 前后台授权:
      在Info.plist文件中配置NSLocationAlwaysUsageDescriptionYES
    - (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(@"定位关闭或者用户未授权");
                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];
    }
    

    控制台打印

    四、地理编码

    定位服务中还包含CLGeocoder类,用于处理地理编码和逆地理编码功能。

    • 地理编码:根据给定的位置(通常是地名)确定地理坐标(经、纬度)。
      【位置 -> 地理坐标】
    • 逆地理编码:可以根据地理坐标(经、纬度)确定位置信息(街道、门牌等)。
      【地理坐标 -> 位置】
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.geocoder = [[CLGeocoder alloc] init];
        [self getCoordinateByAddress:@"北京"];
        [self getAddressByLatitude:39.54 longitude:116.28];
    }
    
    #pragma mark 根据地名确定地理坐标
    -(void)getCoordinateByAddress:(NSString *)address{
        //地理编码
        [self.geocoder geocodeAddressString:address 
                          completionHandler:^(NSArray *placemarks, NSError *error) {
            //取得第一个地标,地标中存储了详细的地址信息,注意:一个地名可能搜索出多个地址
            CLPlacemark *placemark = [placemarks firstObject];
            CLLocation *location = placemark.location;//位置
            CLRegion *region = placemark.region;//区域
            NSDictionary *addressDic = placemark.addressDictionary;//详细地址信息字典
            NSLog(@"位置:%@,区域:%@,详细信息:%@",location,region,addressDic);
        }];
    }
    #pragma mark 根据坐标取得地名
    -(void)getAddressByLatitude:(CLLocationDegrees)latitude 
                      longitude:(CLLocationDegrees)longitude
    {
        //反地理编码
        CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude 
                                                          longitude:longitude];
        [self.geocoder reverseGeocodeLocation:location 
                            completionHandler:^(NSArray *placemarks, NSError *error) {
            CLPlacemark *placemark = [placemarks firstObject];
            NSLog(@"详细信息:%@",placemark.addressDictionary);
        }];
    }
    
    地标类CLPlacemark还包含以下信息:
    NSString *name = placemark.name;//地名
    NSString *thoroughfare = placemark.thoroughfare;//街道
    NSString *subThoroughfare = placemark.subThoroughfare; //街道相关信息,例如门牌等
    NSString *locality = placemark.locality; // 城市
    NSString *subLocality = placemark.subLocality; // 城市相关信息,例如标志性建筑
    NSString *administrativeArea = placemark.administrativeArea; // 州
    NSString *subAdministrativeArea = placemark.subAdministrativeArea; //其他行政区域信息
    NSString *postalCode = placemark.postalCode; //邮编
    NSString *ISOcountryCode = placemark.ISOcountryCode; //国家编码
    NSString *country = placemark.country; //国家
    NSString *inlandWater = placemark.inlandWater; //水源、湖泊
    NSString *ocean = placemark.ocean; // 海洋
    NSArray *areasOfInterest = placemark.areasOfInterest; //关联的或利益相关的地标
    
    下一节我会写地图类MapKit的相关笔记,敬请期待吧!有什么问题可以在下方评论区提出,O(∩_∩)O哈!
  • 相关阅读:
    我的“.vimrc”配置
    js写的简单购物车2
    js写的简单购物车
    用css3绘制你需要的几何图形
    给父级DIV清除浮动
    HTML中canvas的大小调整
    Python
    Python文本编辑器推荐
    jQuery mobile基础
    Bootstrap网格系统
  • 原文地址:https://www.cnblogs.com/liutingIOS/p/5381425.html
Copyright © 2011-2022 走看看