iOS 封装工具类 --代理模式转换block模式-定位

一、需求

  • 写个继承NSObject的工具类JPLocationTool,用block实现传值

二、具体实现

  • 1.JPLocationTool.h文件
#import <Foundation/Foundation.h>
#import "Singleton.h"
#import <CoreLocation/CoreLocation.h>

typedef void(^ResultBlock)(CLLocation *location, CLPlacemark *pl, NSString *error);


@interface JPLocationTool : NSObject
single_interface(JPLocationTool);

- (void)getCurrentLocation:(ResultBlock)block;

@end

  • 2.JPLocationTool.m文件
#import "JPLocationTool.h"
#import <UIKit/UIKit.h>
#define isIOS(version) ([[UIDevice currentDevice].systemVersion floatValue] >= version)

@interface JPLocationTool()<CLLocationManagerDelegate>

/** 回调代码块 */
@property (nonatomic, copy) ResultBlock block;

/** 位置管理者 */
@property (nonatomic, strong) CLLocationManager *locationM;

/** 地理编码 */
@property (nonatomic, strong) CLGeocoder *geoC;

@end

@implementation JPLocationTool
single_implementation(JPLocationTool);

#pragma mark -懒加载
-(CLLocationManager *)locationM
{
    if (!_locationM) {
        _locationM = [[CLLocationManager alloc] init];
        _locationM.delegate = self;
        
        // iOS8.0之后, 必须手动请求定位授权
        // 获取info.plist 里面的键值对
        NSDictionary *infoDic = [NSBundle mainBundle].infoDictionary;
        
//        NSLog(@"%@", infoDic);
        
        if (isIOS(8.0)) {
//            [_locationM requestAlwaysAuthorization];
//            [_locationM requestWhenInUseAuthorization];

            // 获取前后台定位描述(看其他开发者到底有没有添加这个key)
            NSString *alwaysStr = infoDic[@"NSLocationAlwaysUsageDescription"];
            
            // 获取前后台定位描述(看其他开发者到底有没有添加这个key)
            NSString *whenInUseStr = infoDic[@"NSLocationWhenInUseUsageDescription"];
            
            // 判断其它开发者, 到底填写的是哪个key
            if([alwaysStr length] > 0)
            {
                [_locationM requestAlwaysAuthorization];
            }
            else if ([whenInUseStr length] > 0)
            {
                [_locationM requestWhenInUseAuthorization];
                // 如果请求的是前台定位授权, 如果想要在后台获取用户位置, 提醒其他开发者, 勾选后台模式location updates
                NSArray *backModes = infoDic[@"UIBackgroundModes"];
                if (![backModes containsObject:@"location"]) {
                    NSLog(@"当前授权模式是前台定位授权, 如果想要在后台获取位置, 需要勾选后台模式location updates");
                }else // 代表当前勾选后台模式, 而且是前台定位授权
                {
                    if(isIOS(9.0))
                    {
                        _locationM.allowsBackgroundLocationUpdates = YES;
                    }
                }
       
            }else
            {
                NSLog(@"如果在iOS8.0之后获取用户位置, 必须主动填写info.plist文件中的key NSLocationAlwaysUsageDescription 或者 NSLocationWhenInUseUsageDescription");
            }
        }else // ios8.0之前
        {
            // 如果请求的是前台定位授权, 如果想要在后台获取用户位置, 提醒其他开发者, 勾选后台模式location updates
            NSArray *backModes = infoDic[@"UIBackgroundModes"];
            if (![backModes containsObject:@"location"]) {
                NSLog(@"当前授权模式, 如果想要在后台获取位置, 需要勾选后台模式location updates");
            }
        }
    }
    return _locationM;
}


#pragma mark -懒加载
-(CLGeocoder *)geoC
{
    if (!_geoC) {
        _geoC = [[CLGeocoder alloc] init];
    }
    return _geoC;
}

- (void)getCurrentLocation:(ResultBlock)block
{
    // 记录代码块
    self.block = block;
    
    // 获取用户位置信息
    if([CLLocationManager locationServicesEnabled])
    {
        [self.locationM startUpdatingLocation];
    }else
    {
        self.block(nil, nil, @"定位服务未开启");
    }
}

#pragma mark -CLLocationManagerDelegate
/**
 *  定位到之后调用
 *
 *  @param manager   位置管理者
 *  @param locations 位置数组
 */
-(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];
}

/**
 *  当前授权状态发生改变时调用
 *
 *  @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 kCLAuthorizationStatusAuthorizedAlways:
            //        case kCLAuthorizationStatusAuthorized: // 失效,不建议使用
        {
            NSLog(@"获取前后台定位授权");
            break;
        }
            // 获得前台定位授权
        case kCLAuthorizationStatusAuthorizedWhenInUse:
        {
            NSLog(@"获得前台定位授权");
            break;
        }
        default:
            break;
    }
}
@end
  • 3.使用:获取定位信息与地标对象
#import "ViewController.h"
#import "JPLocationTool.h"
@interface ViewController ()

@end

@implementation ViewController


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [[JPLocationTool sharedJPLocationTool] getCurrentLocation:^(CLLocation *location, CLPlacemark *pl, NSString *error) {
        if([error length] > 0)
        {
            NSLog(@"有错误--%@", error);
        }else
        {
            NSLog(@"%@", pl.name);
        }
    }];
}
@end

三、依赖的单例宏 Singleton.h

// .h
#define single_interface(class)  + (class *)shared##class;

// .m
// \ 代表下一行也属于宏
// ## 是分隔符
#define single_implementation(class) \
static class *_instance; \
 \
+ (class *)shared##class \
{ \
    if (_instance == nil) { \
        _instance = [[self alloc] init]; \
    } \
    return _instance; \
} \
 \
+ (id)allocWithZone:(NSZone *)zone \
{ \
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
        _instance = [super allocWithZone:zone]; \
    }); \
    return _instance; \
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容

  • 1、截取字符串”20 | http://www.baidu.com”中,”|”字符前面和后面的数据,分别输出它们 ...
    强子ly阅读 2,934评论 8 46
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,135评论 30 470
  • 在iOS开发中,经常会碰到定位到当前城市的需求,系统自带的定位功能就能实现,于是封装了一个类方便使用,整理一下发出...
    林夕不昔阅读 535评论 3 0
  • 1.OC里用到集合类是什么? 基本类型为:NSArray,NSSet以及NSDictionary 可变类型为:NS...
    轻皱眉头浅忧思阅读 1,368评论 0 3
  • Lancy's Blog Blog Archives About MeTwitterWeiboGitHubRSS ...
    其实也没有阅读 5,479评论 0 24