浅谈——适配所有IOS版本的反地理编码的代理转block封装

LSLLocationTool工具类的声明文件.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import "Single.h"

/** 接口block */
typedef void(^ResultBlock)(CLLocation *location, CLPlacemark *placemark, NSString *error);

@interface LSLLocationTool : NSObject
/** 用宏实现类单利模式的声明 */
SingleInterface(LSLLocationTool);

/** 反地理编码接口 */
- (void)getCurrentLocation:(ResultBlock)block;
@end
LSLLocationTool工具类的实现文件.m

#import "LSLLocationTool.h"
#import <UIKit/UIKit.h>

/** 判断当前ios版本宏 */
#define isIOS(version) ([[UIDevice currentDevice].systemVersion floatValue] >= version)

@interface LSLLocationTool()<CLLocationManagerDelegate>
/** 回调代码 */
@property(nonatomic,copy)ResultBlock block;
/** 位置管理者 */
@property(nonatomic,strong)CLLocationManager *locationManager;
/** 地理编码 */
@property(nonatomic,strong)CLGeocoder *geocoder;
@end

@implementation LSLLocationTool
/** 用宏实现类单利模式的实现 */
SingleImplement(LSLLocationTool);

#pragma mark - 懒加载
- (CLLocationManager *)locationManager
{
    if (!_locationManager) {
        _locationManager = [[CLLocationManager alloc] init];
        _locationManager.delegate = self;

        // 获取info.plist 里面的键值对
        NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary];

        // iOS8.0之后, 必须手动请求定位授权
        if (isIOS(8.0)) {
            // 获取前后台定位描述(看其他开发者到底有没有添加这个key)
            NSString *alwaysStr = infoDict[@"NSLocationAlwaysUsageDescription"];

            // 获取前后台定位描述(看其他开发者到底有没有添加这个key)
            NSString *whenInUseStr = infoDict[@"NSLocationWhenInUseUsageDescription"];

            // 判断其它开发者, 到底填写的是哪个key
            if([alwaysStr length] > 0){
                [_locationManager requestAlwaysAuthorization];
            }else if ([whenInUseStr length] > 0){
                [_locationManager requestWhenInUseAuthorization];

                // 如果请求的是前台定位授权, 如果想要在后台获取用户位置, 提醒其他开发者, 勾选后台模式location updates
                NSArray *backModes = infoDict[@"UIBackgroundModes"];

                if (![backModes containsObject:@"location"]) {
                    NSLog(@"当前授权模式是前台定位授权, 如果想要在后台获取位置, 需要勾选后台模式location updates");

                }else { // 代表当前勾选后台模式, 而且是前台定位授权
                    if(isIOS(9.0)){
                        _locationManager.allowsBackgroundLocationUpdates = YES;
                    }
                }
            }else{
                NSLog(@"如果在iOS8.0之后获取用户位置, 必须主动填写info.plist文件中的key NSLocationAlwaysUsageDescription 或者 NSLocationWhenInUseUsageDescription");
            }
        }else{// ios8.0之前
            // 如果请求的是前台定位授权, 如果想要在后台获取用户位置, 提醒其他开发者, 勾选后台模式location updates
            NSArray *backModes = infoDict[@"UIBackgroundModes"];
            if (![backModes containsObject:@"location"]) {
                NSLog(@"当前授权模式, 如果想要在后台获取位置, 需要勾选后台模式location updates");
            }
        }
    }
    return _locationManager;
}

- (CLGeocoder *)geocoder
{
    if (!_geocoder) {
        _geocoder = [[CLGeocoder alloc] init];
    }
    return _geocoder;
}

#pragma mark - 反地理编码接口的实现
- (void)getCurrentLocation:(ResultBlock)block
{
    // 记录代码块
    self.block = block;

    // 判断用户是否开启定位
    if ([CLLocationManager locationServicesEnabled] ) {
        [self.locationManager startUpdatingLocation];
    }else{
        self.block(nil,nil,@"用户未开启定位服务");
    }
}

#pragma mark - <CLLocationManagerDelegate> 实现代理方法
/**
 *  定位到之后调用
 *
 *  @param manager   位置管理者
 *  @param locations 位置数组
 */
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
    CLLocation *location = [locations firstObject];

    // 判断位置是否可用
    if (location.horizontalAccuracy >= 0) {
        [self.geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
            if (error == nil) {
                CLPlacemark *placemark = [placemarks firstObject];

                self.block(location,placemark,nil);
            }else{
                self.block(location,nil,@"反编码失败");
            }
        }];
    }

    // 只需要获取用户位置一次,则直接停止
    [manager stopUpdatingLocation];
}

/**
 *  当前授权状态发生改变时调用
 *
 *  @param manager 位置管理者
 *  @param status  状态
 */
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    switch (status) {
            // 用户还未决定
        case kCLAuthorizationStatusNotDetermined:
        {
            NSLog(@"用户还未决定");
            break;
        }
            // 问受限
        case kCLAuthorizationStatusRestricted:
        {
            NSLog(@"访问受限");
            self.block(nil, nil, @"访问受限");
            break;
        }
            // 定位关闭时和对此APP授权为never时调用
        case kCLAuthorizationStatusDenied:
        {
            // 定位是否可用(是否支持定位或者定位是否开启)
            if([CLLocationManager locationServicesEnabled])
            {
                NSLog(@"定位开启,但被拒");
                self.block(nil, nil, @"被拒绝");
            }else
            {
                NSLog(@"定位关闭,不可用");
                self.block(nil, nil, @"定位关闭,不可用");
            }
            break;
        }
            // 获取前后台定位授权
        // case kCLAuthorizationStatusAuthorized: // 失效,不建议使用
        case kCLAuthorizationStatusAuthorizedAlways:
        {
            NSLog(@"获取前后台定位授权");
            break;
        }
            // 获得前台定位授权
        case kCLAuthorizationStatusAuthorizedWhenInUse:
        {
            NSLog(@"获得前台定位授权");
            break;
        }
        default:
            break;
    }
}
@end
使用示例:
#import "ViewController.h"
#import "LSLLocationTool.h"

@interface ViewController ()
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];

    [[LSLLocationTool shareLSLLocationTool] getCurrentLocation:^(CLLocation *location, CLPlacemark *placemark, NSString *error) {
        if([error length] > 0){
            NSLog(@"报错--%@", error);
        }else{
            NSLog(@"%@", placemark.name);
        }
    }];
}
@end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值