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

来源:互联网 发布:ps for mac如何破解 编辑:程序博客网 时间:2024/05/17 15:58

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)

  • 下载地址
    https://github.com/intuit/LocationManager
0 0