iOS开发 - 23.实用技术之定位

0 专业术语

  • LBS(Location Based Service)
  • SoLoMo(Social Location Mobile)(所罗门)

1.基本使用

  • CLLocationManager
    • 创建管理者对象
    • 开始获取位置(开发经验:start 开始某个服务 stop 停止某个服务)

iOS 8.0以前

// 前台定位
// 1. 导入CoreLocation框架和对应的主头文件
#import <CoreLocation/CoreLocation.h>
// 2. 创建CLLcationManager对象,并设置代理
_locationM = [[CLLocationManager alloc] init];
_locationM.delegate = self;
// 3. 调用CLLcationManager对象的startUpdatingLocation方法进行更新用户位置
[_locationM startUpdatingLocation];
// 4. 实现代理方法,接收位置参数
-(void)locationManager:(nonnull CLLocationManager *)manager didUpdateLocations:(nonnull NSArray<CLLocation *> *)locations
  • 后台定位
    • 在项目配置中设置后台定位服务

iOS8.0

  • 前台定位
  • 1.导入CoreLocation框架和对应的主头文件
#import <CoreLocation/CoreLocation.h>
  • 2.创建CLLcationManager对象,并设置代理
_locationM = [[CLLocationManager alloc] init];
_locationM.delegate = self;
  • 2.1 配置前台请求权限
[_locationM requestWhenInUseAuthorization];
  • 2.2 配置info.plist文件key说明
  • 3.调用CLLcationManager对象的startUpdatingLocation方法进行更新用户位置
[_locationM startUpdatingLocation];
  • 4.实现代理方法,接收位置参数
-(void)locationManager:(nonnull CLLocationManager *)manager didUpdateLocations:(nonnull NSArray<CLLocation *> *)locations
  • 后台定位
  • 方法一:
    • 在项目配置中设置后台定位服务
    • 注意:如果APP处于后台,则会出现蓝条
  • 方法二:

    • 请求前后台权限
      [_manager requestAlwaysAuthorization];
    • 配置info.plist文件key说明
  • 监听权限状态改变

// 在状态授权状态时调用
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
    /**
     typedef NS_ENUM(int, CLAuthorizationStatus) {
     kCLAuthorizationStatusNotDetermined = 0, 用户未确定
     kCLAuthorizationStatusRestricted, 受限
     kCLAuthorizationStatusDenied, 被拒绝
     kCLAuthorizationStatusAuthorizedAlways NS_ENUM_AVAILABLE(NA, 8_0),前后台权限
     kCLAuthorizationStatusAuthorizedWhenInUse NS_ENUM_AVAILABLE(NA, 8_0), 前台可用
     kCLAuthorizationStatusAuthorized  // 过期,等同于kCLAuthorizationStatusAuthorizedAlways
     };
     */

    switch (status) {
        case kCLAuthorizationStatusNotDetermined:
            NSLog(@"用户未确定");
            break;
        case kCLAuthorizationStatusRestricted:
            NSLog(@"定位受限");
            break;
        case kCLAuthorizationStatusDenied:{
            if ([CLLocationManager locationServicesEnabled]) { // 判断定位是否可用
                NSLog(@"定位被开启,但被拒绝");
            }else{
                NSLog(@"定位关闭,不可用");
            }
            break;
        }
        case kCLAuthorizationStatusAuthorizedAlways:
            NSLog(@"进入后台");
            break;
        case kCLAuthorizationStatusAuthorizedWhenInUse:
            NSLog(@"进入前台");
            break;
        default:
            break;
    }
}

iOS9.0

// 前台定位和iOS8一致
// 后台定位方法一:在配置完后台定位后需设置如下属性
_manager.allowsBackgroundLocationUpdates = YES;
// 注意:如果APP处于后台,则会出现蓝条
// 方法二和iOS8一致
  • 补充(请求定位)
// 作用:按照定位精确度从低到高进行排序,逐个进行定位。如果获取到的位置不是精确度最高的那个,也会在定位超时后,通过代理告诉外界
// 注意:一个要实现代理的定位失败方法; 二:不能与startUpdatingLocation同时使用
[_locationM requestLocation];
  • 指南针
- (CLLocationManager *)manager{
    if (!_manager) {
        _manager = [[CLLocationManager alloc] init];
        _manager.delegate = self;
        // 请求授权
        if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
            [_manager requestAlwaysAuthorization];
        }
    }
    return _manager;
}

- (void)viewDidLoad{
    [super viewDidLoad];

    // 开始定位,获取设备朝向
    [self.manager startUpdatingHeading];
}
// 代理方法
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading{
    // 获取当前设备的磁北朝向
    CLLocationDirection angle = newHeading.magneticHeading;

    // 将当前角度转换为弧度值
    CGFloat radius = angle / 180.0 * M_PI;

    // 旋转指南针
    [UIView animateWithDuration:0.25 animations:^{
        self.compass.transform = CGAffineTransformMakeRotation(-radius);
    }];

}

2.区域监听

  • 1.导入CoreLocation框架和对应的主头文件
#import <CoreLocation/CoreLocation.h>
  • 2.创建CLLcationManager对象,并设置代理,请求授权(iOS8.0之后才需要) 请求前后台定位授权,并配置KEY
_locationM = [[CLLocationManager alloc] init];
_locationM.delegate = self;
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0){
    [_locationM requestAlwaysAuthorization];
}
  • 3.调用CLLcationManager对象的startMonitoringForRegion:方法进行监听指定区域
// 创建区域中心
CLLocationCoordinate2D coordinate2D = CLLocationCoordinate2DMake(20.0, 120.0);
// 区域半径
CLLocationDistance distance = 1000;
// 创建区域
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:coordinate2D radius:distance identifier:@"广州"];
// 开始请求定位
[self.manager startMonitoringForRegion:region];
  • 4.实现代理方法,获取区域进入或者离开状态
#pragma mark - CLLocationManagerDelegate
// 进入区域时调用
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{
    NSLog(@"进入区域");
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region{
    NSLog(@"离开区域");
}

3.地理编码(反地理编码)

  • 1.导入CoreLocation框架和对应的主头文件
#import <CoreLocation/CoreLocation.h>
  • 2.创建CLGeocoder对象
_geoC = [[CLGeocoder alloc] init];
  • 3.地理编码
// 方式一:通过位置名称获取编码信息
- (IBAction)geoc:(id)sender {

    NSString *address = self.addressDetailTV.text;
    if (!address.length) return;
    [self.geoC geocodeAddressString:address completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        // 包含区,街道等信息的地标对象
        CLPlacemark *placemark = [placemarks firstObject];
        // 城市名称
        //        NSString *city = placemark.locality;
        // 街道名称
        //        NSString *street = placemark.thoroughfare;
        // 全称
        if(error == nil){
        NSString *name = placemark.name;
        self.addressDetailTV.text = [NSString stringWithFormat:@"%@", name];
        self.latitudeTF.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.latitude];
        self.longtitudeTF.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.longitude];
        }else{
            NSLog(@"编码错误-%@",error);
        }
    }];
// 方式二:
// 地理编码方案二:根据地址和指定区域两个条件进行地理编码(更加精确)
    [self.geoC geocodeAddressString:@"广州" inRegion:nil completionHandler:^(NSArray<CLPlacemark *> * __nullable placemarks, NSError * __nullable error) {
    // 包含区,街道等信息的地标对象
    CLPlacemark *placemark = [placemarks firstObject];
    self.addressDetailTV.text = placemark.description;
    self.latitudeTF.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.latitude];
    self.longtitudeTF.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.longitude];
}];
}
  • 4.反地理编码
// 反地理编码
- (IBAction)reverse:(id)sender {
    /**
     参数一:将要反编码的位置
     参数二:反编码后的回调
     */
    CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake([self.latitudeTF.text floatValue], [self.longtitudeTF.text floatValue]);
    CLLocation *location = [[CLLocation alloc] initWithLatitude:coordinate.latitude longitude:coordinate.longitude];
    [self.geoC reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
         CLPlacemark *placemark = [placemarks firstObject];

        if(error == nil){
            NSString *name = placemark.name;
            self.addressDetailTV.text = name;
            self.latitudeTF.text = @(placemark.location.coordinate.latitude).stringValue ;
            self.longtitudeTF.text = @(placemark.location.coordinate.longitude).stringValue;
        }else{
            NSLog(@"编码错误-%@",error);
        }
    }];
}

4.第三方框架(LocationManager)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值