美文网首页
IOS基础:定位

IOS基础:定位

作者: 时光啊混蛋_97boy | 来源:发表于2020-11-06 15:00 被阅读0次

    原创:知识点总结性文章
    创作不易,请珍惜,之后会持续更新,不断完善
    个人比较喜欢做笔记和写总结,毕竟好记性不如烂笔头哈哈,这些文章记录了我的IOS成长历程,希望能与大家一起进步
    温馨提示:由于简书不支持目录跳转,大家可通过command + F 输入目录标题后迅速寻找到你所需要的内容

    目录

    • 一、CoreLocation
      • 1、用户授权
      • 2、设置定位管理者
      • 3、获取用户当前的位置
      • 4、磁力感应
      • 5、区域检测
      • 6、地理编码与反地理编码

    1、用户授权

    a、运行效果
    用户授权
    2020-11-06 11:12:32.676599+0800 LocationDemo[52957:5777093] 等待用户授权
    2020-11-06 11:13:28.432218+0800 LocationDemo[52957:5777093] 授权成功,开始定位
    
    b、Info.plist添加定位权限

    Privacy - Location When In Use Usage Description:需要使用定位权限
    Privacy - Location Always and When In Use Usage Description:需要使用定位权限

    c、CLAuthorizationStatus
    kCLAuthorizationStatusNotDetermined //用户从未选择过权限,无法使用定位服务,该状态用户无法改变
    kCLAuthorizationStatusRestricted //用户拒绝该应用使用定位服务,或是定位服务总开关处于关闭状态
    kCLAuthorizationStatusDenied //用户允许该程序无论何时都可以使用地理信息
    kCLAuthorizationStatusAuthorizedAlways //用户同意程序在可见时使用地理位置
    kCLAuthorizationStatusAuthorizedWhenInUse //用户同意使用时应用使用定位服务
    
    d、授权状态发生改变时调用
    - (void)locationManagerDidChangeAuthorization:(CLLocationManager *)manager
    {
    
        if (manager.authorizationStatus == kCLAuthorizationStatusNotDetermined)
        {
            NSLog(@"等待用户授权");
        }
        else if (manager.authorizationStatus == kCLAuthorizationStatusAuthorizedAlways || manager.authorizationStatus == kCLAuthorizationStatusAuthorizedWhenInUse)
        {
            NSLog(@"授权成功,开始定位");
            [self.mgr startUpdatingLocation];
        }
        else
        {
            NSLog(@"授权失败");
        }
    }
    

    2、设置定位管理者

    a、引入定位头文件
    #import <CoreLocation/CoreLocation.h>
    
    @interface CoreLocationViewController ()<CLLocationManagerDelegate>
    
    @property (nonatomic ,strong) CLLocationManager *locationManager;// 定位管理者
    
    @end
    
    b、设置定位管理者的属性
    - (void)configLocationManager
    {
        self.place = @"";
        
        // 判断定位权限是否打开
        if ([CLLocationManager locationServicesEnabled])
        {
            _locationManager = [[CLLocationManager alloc] init];
            // 成为CoreLocation管理者的代理监听获取到的位置
            _locationManager.delegate = self;
            
            // 设置寻址精度
            _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
            
            // 设置多远获取一次
            _locationManager.distanceFilter = 100.0f;
            
            // 开始定位
            [_locationManager startUpdatingLocation];
        }
        else
        {
            // 必须再info.plist文件中配置一项属性才能弹出授权窗口
            // 要主动请求授权定位权限 授权状态改变就会通知代理
            [_locationManager requestAlwaysAuthorization];
        }
    }
    

    3、获取用户当前的位置

    a、运行效果
    2020-11-06 11:30:33.256619+0800 LocationDemo[926:133009] 纬度:24.477126,经度:118.183663,速度:-1.000000
    2020-11-06 11:30:33.492373+0800 LocationDemo[926:133009] 在下当前所在位置位:省:福建省,市:厦门市,街道:思明区 展鸿路81号
    
    b、位置信息

    可以设置模拟器模拟速度

    bicycle ride// 骑车移动
    run// 跑动
    freeway drive// 高速公路驾车
    

    可以获取到的位置信息

    location.coordinate; //坐标, 包含经纬度
    location.altitude; //设备海拔高度 单位是米
    location.course; //设置前进方向 0表示北 90东 180南 270西
    location.horizontalAccuracy; //水平精准度
    location.verticalAccuracy; //垂直精准度
    location.timestamp; //定位信息返回的时间
    location.speed; //设备移动速度 单位是米/秒, 适用于行车速度而不太适用于不行
    
    c、获取到位置信息之后就会调用(调用频率非常高)
    - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
    {
        // 如果只需要获取一次, 可以获取到位置之后就停止
        [_locationManager stopUpdatingHeading];
        [_locationManager stopUpdatingLocation];
        
        // 获取最后一次的位置
        CLLocation *location = [locations lastObject];
        NSLog(@"纬度:%f,经度:%f,速度:%f", location.coordinate.latitude, location.coordinate.longitude, location.speed);
        
        CLLocation *currentLocation = [locations lastObject];
        CLGeocoder *geoCoder = [[CLGeocoder alloc] init];
        // 利用经纬度进行反编译获取位置信息
        [geoCoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
            if (placemarks.count > 0)
            {
                // 获取当前定位信息
                CLPlacemark *placeMark = [placemarks firstObject];
                if (placeMark)
                {
                    //省、市、县、街
                    self.place = [NSString stringWithFormat:@"省:%@,市:%@,街道:%@ %@",placeMark.administrativeArea,placeMark.locality,placeMark.subLocality,placeMark.thoroughfare];
                    NSLog(@"在下当前所在位置位:%@",self.place);
                }
            }
        }];
    }
    
    d、定位失败时调用
    - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
    {
        [_locationManager startUpdatingLocation];
    }
    

    4、磁力感应

    a、运行效果
    磁力感应
    2020-11-06 13:51:35.295963+0800 LocationDemo[1309:196044] 设备支持则开启磁力感应
    2020-11-06 13:51:35.364536+0800 LocationDemo[1309:196044] 设备与磁北的相对角度:232.313324
    
    b、判断设备是否支持则开启磁力感应
    if ([CLLocationManager headingAvailable])
    {
        self.mgr.headingFilter = kCLHeadingFilterNone;
        [self.mgr startUpdatingHeading];
        
        NSLog(@"设备支持则开启磁力感应");
    }
    else
    {
        NSLog(@"设备不支持则开启磁力感应");
    }
    
    c、当获取到用户方向时就会调用
    - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
    {
        // magneticHeading: 设备与磁北的相对角度
        // trueHeading:设置与真北的相对角度,真北始终指向地理北极点,必须和定位一起使用,iOS需要设置的位置来计算真北
        NSLog(@"设备与磁北的相对角度:%f",newHeading.magneticHeading);
    
        // 将获取到的角度转为弧度 = (角度 * π) / 180;
        CGFloat angle = newHeading.magneticHeading * M_PI / 180;
    
        // 如果需要根据角度来旋转图片如指南针等,可以这样调用
        // 顺时针 正  逆时针 负
        self.compasspointer.transform = CGAffineTransformMakeRotation(-angle);
    }
    

    5、区域检测

    a、监听区域
    - (void)areaDetection
    {
        // 创建中心点
        CLLocationCoordinate2D center = CLLocationCoordinate2DMake(24.477117, 118.183691);
        // 创建圆形区域, 指定区域中心点的经纬度, 以及半径
        CLCircularRegion *circular = [[CLCircularRegion alloc] initWithCenter:center radius:0.1 identifier:@"厦门"];
        [_locationManager startMonitoringForRegion:circular];
    }
    
    b、进入监听区域时调用
    - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
    {
        NSLog(@"进入监听区域时调用");
    }
    
    c、进入监听区域时调用
    - (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
    {
        NSLog(@"离开监听区域时调用");
    }
    

    6、地理编码与反地理编码

    a、运行效果
    2020-11-06 14:55:09.540017+0800 LocationDemo[1463:228984] name=福建省厦门市思明区岭兜南片区156号楼 locality=厦门市 country=中国 postalCode=(null)
    2020-11-06 14:55:09.540113+0800 LocationDemo[1463:228984] 地理编码,获取到的详细地址名称:福建省厦门市思明区岭兜南片区156号楼,纬度:24.48,经度:118.18
    2020-11-06 14:55:09.480586+0800 LocationDemo[1463:228984] 反地理编码获取到的位置名称为: 岭兜南片区156号楼
    
    b、地理编码: 地名—>经纬度坐标
    - (void)geocoding
    {
        // 根据传入的地址获取该地址对应的经纬度信息
        CLGeocoder *geocoder = [[CLGeocoder alloc] init];
        [geocoder geocodeAddressString:@"岭兜南片区156号楼" completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
            
            // 如果有错误信息,或者是数组中获取的地名元素数量为0,那么说明没有找到
            if (error || placemarks.count == 0)
            {
                NSLog(@"你输入的地址没找到,可能在月球上");
            }
            else
            {
                // 打印查看找到的所有的位置信息
                // locality:城市  country:国家 postalCode:邮政编码
                for (CLPlacemark *placemark in placemarks)
                {
                    NSLog(@"name=%@ locality=%@ country=%@ postalCode=%@",placemark.name, placemark.locality, placemark.country, placemark.postalCode);
                }
                
                // 取出获取的地理信息数组中的第一个显示在界面上
                CLPlacemark *firstPlacemark = [placemarks firstObject];
                
                // 详细地址名称
                NSString *latitude = [NSString stringWithFormat:@"%.2f",firstPlacemark.location.coordinate.latitude];
                NSString *longitude = [NSString stringWithFormat:@"%.2f",firstPlacemark.location.coordinate.longitude];
                NSLog(@"地理编码,获取到的详细地址名称:%@,纬度:%@,经度:%@",firstPlacemark.name,latitude,longitude);
            }
        }];
    }
    
    c、反地理编码:经纬度坐标—>地名
    - (void)antiGeocoding
    {
        CLGeocoder *geocoder = [[CLGeocoder alloc] init];
        
        // 1.获得输入的经纬度
        CLLocationDegrees latitude = [@"24.477139" doubleValue];
        CLLocationDegrees longitude = [@"118.183671" doubleValue];
        CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
        
        // 2.反地理编码
        [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error)
         {
            if (error||placemarks.count==0)
            {
                NSLog(@"你输入的地址没找到,可能在月球上");
            }
            else
            {
                // 显示最前面的地标信息
                CLPlacemark *firstPlacemark= [placemarks firstObject];
                // 详细地址名称
                NSLog(@"反地理编码获取到的位置名称为: %@",firstPlacemark.name);
            }
        }];
    }
    

    Demo

    Demo在我的Github上,欢迎下载。
    LocationDemo

    参考文献

    相关文章

      网友评论

          本文标题:IOS基础:定位

          本文链接:https://www.haomeiwen.com/subject/rfozvktx.html