iOS定位工具类--block传值

作者: 林夕不昔 | 来源:发表于2017-09-24 15:36 被阅读36次

    在iOS开发中,经常会碰到定位到当前城市的需求,系统自带的定位功能就能实现,于是封装了一个类方便使用,整理一下发出来共勉,大家多提意见,多多交流😁

    使用

    可实现定位到当前地址的功能,调用简单,block传值

     [[MSLocationTool sharedMSLocationTool] getCurrentLOcation:^(CLLocation *location, CLPlacemark *pl, NSString *error) {
             if ([error length] > 0) {
                 NSLog(@"定位有错误-->%@",error);   
             }else{
                 [self.locationBtn setTitle:pl.locality forState:UIControlStateNormal];
                    
                 [[NSUserDefaults standardUserDefaults] setValue:pl.locality forKey:CITY_KEY];
                 [[NSUserDefaults standardUserDefaults] synchronize];
                    
             }
                
    }];
    
    

    实现

    • 第一步:请求授权

    在Info.plist中配置相关key:
    Privacy - Location When In Use Usage Description
    Privacy - Location Always Usage Description

    //后面为字符串类型(随意填写) 例如:请您允许,我们将会为您提供更精确的信息
    Privacy - Location When In Use Usage Description   
    //后面为字符串类型(随意填写)例如:请您允许,我们将会为您提供更精确的信息 
    Privacy - Location Always Usage Description        
    // 特别声明一下,这个字段的添加要看你的需求,这个功能是指在后台时也可以时时定位,
    所以app如果不需要的话,不建议添加,否则上线审核会出现问题,
    如果需要这个功能,要做一些声明描述:GPS在后台持续运行,可以大大降低电池的寿命。
    
    info.plist配置.png
    • 第二步:单例宏

    创建一个Header File来实现单例宏,Singleton.h内容如下:

    Singleton.png
    #ifndef Singleton_h
    #define Singleton_h
    
    /**
     *  在.h文件中定义的宏,arc
     *
     *  MSSingletonH(name) 这个是宏
     *  + (instancetype)shared##name;这个是被代替的方法, ##代表着shared+name 高度定制化
     * 在外边我们使用 “MSSingletonH(gege)” 那么在.h文件中,定义了一个方法"+ (instancetype)sharedgege",所以,第一个字母要大写
     *
     *  @return 一个搞定好的方法名
     */
    #define MSSingletonH(name) + (instancetype)shared##name;
    
    
    /**
     *  在.m文件中处理好的宏 arc
     *
     *  MSSingletonM(name) 这个是宏,因为是多行的东西,所以每行后面都有一个"\",最后一行除外,
     * 之所以还要传递一个“name”,是因为有个方法要命名"+ (instancetype)shared##name"
     *  @return 单利
     */
    #define MSSingletonM(name) \
    static id instance_ = nil;\
    + (instancetype)shared##name{\
    static dispatch_once_t onceToken;\
    dispatch_once(&onceToken, ^{\
    instance_ = [[self alloc] init];\
    });\
    return instance_;\
    }\
    + (instancetype)allocWithZone:(struct _NSZone *)zone{\
    static dispatch_once_t onceToken;\
    dispatch_once(&onceToken, ^{\
    instance_ = [super allocWithZone:zone];\
    });\
    return instance_;\
    }\
    - (id)copyWithZone:(NSZone *)zone{\
    return instance_;\
    }
    
    #endif /* Singleton_h */
    
    
    
    • 第三步:继承自NSObject的工具类MSLocationTool

    工具类继承自NSObject。

    MSLocationTool.h文件内容如下:
    1、导入系统自带的库#import <CoreLocation/CoreLocation.h>;
    2、单例;
    3、block实现返回值

    #import <Foundation/Foundation.h>
    #import "Singleton.h"
    #import <CoreLocation/CoreLocation.h>
    
    
    typedef void(^ResultCityBlock)(CLLocation *location,CLPlacemark *pl,NSString *error);
    
    
    @interface MSLocationTool : NSObject
    
    
    MSSingletonH(MSLocationTool)
    
    -(void)getCurrentLOcation:(ResultCityBlock)block;
    
    
    @end
    
    

    MSLocationTool.m文件内容如下:

    1、导入头文件,属性声明
    2、方法实现

    #import "MSLocationTool.h"
    #import <UIKit/UIKit.h>
    #import "Singleton.h"
    
    #define isIOS(version) ([[UIDevice currentDevice].systemVersion floatValue] >= version)
    
    @interface MSLocationTool()<CLLocationManagerDelegate>
    
    @property(nonatomic,copy)ResultCityBlock block;
    
    /** manager */
    @property(nonatomic,strong)CLLocationManager *locationManager;
    
    /** 地理编码 */
    @property(nonatomic,strong)CLGeocoder *geoC;
    
    
    @end
    
    
    @implementation MSLocationTool
    
    //单例
    MSSingletonM(MSLocationTool)
    
    #pragma mark - 懒加载
    -(CLLocationManager *)locationManager
    {
        if (_locationManager == nil) {
            _locationManager = [[CLLocationManager alloc] init];
            _locationManager.delegate = self;
            
            //获取info.plist里的键值对
            NSDictionary *infoDict = [NSBundle mainBundle].infoDictionary;
            
            
            if (isIOS(8.0)) {
                
                //获取后台定位描述
                NSString *alwaysStr = infoDict[@"NSLocationAlwaysUsageDescription"];
                NSString *whenUserStr = infoDict[@"NSLocationWhenInUseUsageDescription"];
                
                // 根据开发者的设置 请求定位授权
                if ([alwaysStr length] > 0) {
                    [_locationManager requestAlwaysAuthorization];
                    
                }else if ([whenUserStr length] > 0){
                    [_locationManager requestWhenInUseAuthorization];
                    
                    NSArray *backModels = infoDict[@"UIBackgroundModes"];
                    if (![backModels containsObject:@"location"]) {
                        //前台定位授权,如果想在后台获取位置,需勾选后台模式location update
                        
                    }else{
                        if (isIOS(9.0)) {
                            _locationManager.allowsBackgroundLocationUpdates = YES;
                        }
                        
                    }
                    
                    
                }
         
                
            }else{
                // 如果请求的是前台定位授权, 如果想要在后台获取用户位置, 提醒其他开发者, 勾选后台模式location updates
                NSArray *backModes = infoDict[@"UIBackgroundModes"];
                if (![backModes containsObject:@"location"]) {
                    NSLog(@"当前授权模式, 如果想要在后台获取位置, 需要勾选后台模式location updates");
                }
                
                
            }
            
            
        }
        
        return _locationManager;
    }
    
    -(CLGeocoder *)geoC
    {
        if (_geoC == nil) {
            _geoC = [[CLGeocoder alloc] init];
        }
        return _geoC;
    }
    
    #pragma mark - 方法
    -(void)getCurrentLOcation:(ResultCityBlock)block
    {
        //记录代码块
        self.block = block;
        
        //获取位置信息
        if ([CLLocationManager locationServicesEnabled]) {
            
            [self.locationManager startUpdatingLocation];
            
        }else{
            self.block(nil, nil, @"定位服务未开启");
            
        }
    }
    
    #pragma mark - 代理方法
    -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
    {
        CLLocation *location = [locations lastObject];
        
        //判断位置是否可用
        if (location.horizontalAccuracy >= 0) {
            [self.geoC reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
               
                if (error == nil) {
                    CLPlacemark *pl = [placemarks firstObject];
                    self.block(location, pl, nil);
                    
                }else{
                    self.block(location, nil, @"反地理编码失败");
                    
                }
                
                
            }];
        }
        
        [manager stopUpdatingLocation];
        
    }
    
    -(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 kCLAuthorizationStatusAuthorizedAlways:
                NSLog(@"获取前后台定位授权");
                break;
                
            case kCLAuthorizationStatusAuthorizedWhenInUse:
                NSLog(@"获取前台定位授权");
                break;
                
                
                
            default:
                break;
        }
    }
    
    @end
    
    

    参考链接
    代码附上--GitHub链接

    相关文章

      网友评论

        本文标题:iOS定位工具类--block传值

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