IOS基础:定位

2020-11-06  本文已影响0人  时光啊混蛋_97boy

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

目录

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

参考文献

上一篇 下一篇

猜你喜欢

热点阅读