手把手教你封裝一個(gè)獲取定位的管理類(lèi)

源碼地址

直接上重點(diǎn),先把地址放出來(lái),比較著急的,可以直接拿取用,傳送門(mén):https://github.com/wxh794708907/YJYYLocationManager

前言

首先說(shuō)說(shuō)為什么要封裝這個(gè)饥脑,我記得我做的前幾個(gè)項(xiàng)目中都用到了獲取用戶(hù)定位的功能,當(dāng)時(shí)是基于百度地圖或者是高德地圖來(lái)做的懦冰,所以當(dāng)時(shí)并沒(méi)有涉及到自己去封裝一個(gè)管理類(lèi)的想法灶轰,目前在做的項(xiàng)目中由于沒(méi)有繼承百度地圖/高德地圖但是需要用到用戶(hù)定位、用戶(hù)和主播之間的距離刷钢、用戶(hù)城市等信息笋颤,因此特意封裝了一個(gè)獲取定位、計(jì)算兩個(gè)坐標(biāo)距離等功能的管理類(lèi),防止以后再用到時(shí)都寫(xiě)重復(fù)的代碼伴澄。順便帶著不熟悉CoreLocation框架的簡(jiǎn)友們一起來(lái)封裝一個(gè)工具類(lèi)赋除。

CoreLocation的使用

封裝之前我們還是來(lái)看看不封裝時(shí)CoreLocation怎么用的,如果不會(huì)用那封裝就不用說(shuō)了非凌,不過(guò)這篇文章我不想再談CoreLocation的使用举农,因?yàn)槲以诤芫靡郧皩?xiě)過(guò)一篇文章專(zhuān)門(mén)來(lái)介紹CoreLocation的使用,所以如果各位看官不熟悉CoreLocation使用的敞嗡,先去看看我以前的文章介紹颁糟。傳送門(mén):http://www.reibang.com/p/a0ba17eda84e

封裝第一步 接口的定制

無(wú)論是封裝什么工具類(lèi),第一步我覺(jué)得是考慮好自己的需求喉悴,需要做什么棱貌,然后再根據(jù)需求來(lái)定制接口,就以我們今天的需求來(lái)說(shuō)粥惧,我們是需要獲取用戶(hù)的地理位置键畴,那么我們定制接口的時(shí)候肯定是需要有經(jīng)緯度或者地名之類(lèi)的參數(shù)或者返回值,考慮到使用的簡(jiǎn)便和獲取定位的異步性突雪,這里我們使用block的形式來(lái)做,接口定義如下:

/**
 創(chuàng)建地理位置管理單例

 @return 返回地理位置管理單例
 */
+ (instancetype)sharedManager;


/**
 更新地理位置

 @param locationCB 定位成功回調(diào)
 */
- (void)updateLocationWithLocation:(void(^)(CLLocation *location))locationCB failureCB:(void(^)(NSError *error))failureCB;


/**
 傳入經(jīng)緯度返回地名

 @param location location
 @param callBack 反編碼成功回調(diào)
 */
- (void)reverseGeocodeLocation:(CLLocation *)location callBack:(void(^)(NSString * place))callBack;


/**
 獲取定位后反編碼之后用戶(hù)位置

 @param callBack 反編碼成功之后的回調(diào)
 */
- (void)updateReverseGeocodeLocation:(void(^)(NSString *placeName))callBack;


/**
 更新速度信息
 
 @param callBack 速度變化回調(diào)
 */
-(void)updateSpeedWithCallBack:(void(^)(CLLocationSpeed speed)) callBack;


/**
 計(jì)算相對(duì)距離(km)
 
 @param startCoordinate 起點(diǎn)
 @param targetCoordinate 目標(biāo)位置
 @return 相對(duì)距離
 */
-(CLLocationDistance)distanceFromCoordinate:(CLLocationCoordinate2D)startCoordinate
                 toTargetCoordinate:(CLLocationCoordinate2D) targetCoordinate;

/**
 計(jì)算當(dāng)前位置到目標(biāo)位置的相對(duì)距離(km)
 
 @param targetCoordinate 目標(biāo)位置
 */
-(void)distanceFromCurrentLocationToTargetLocation:(CLLocationCoordinate2D) targetCoordinate callBack:(void(^)(CLLocationDistance distance))callBack;


當(dāng)然這里我們還必須有管理單例的創(chuàng)建接口涡贱,此外我們?cè)讷@取定位失敗時(shí)也需要有回調(diào)咏删,所以這里我們還加入了失敗的回調(diào)。

封裝第二部 接口的實(shí)現(xiàn)

接口的定制我們已經(jīng)做完了问词,接下來(lái)就該來(lái)實(shí)現(xiàn)了督函,我們獲取定位是根據(jù)蘋(píng)果的代理回調(diào)來(lái)做的,但是我們?cè)谶@個(gè)方法實(shí)現(xiàn)里是獲取不到定位的激挪,怎么辦辰狡?添加全局屬性來(lái)關(guān)聯(lián)啊。具體實(shí)現(xiàn)如下:

#import "YJYYLocationManager.h"
#import <CoreLocation/CoreLocation.h>
typedef void(^YJYYLocationBlock)(CLLocation *location);
typedef void(^YJYYFailureBlock)(NSError *error);
typedef void(^YJYYReverseGeoBlock)(NSString *placeName);
typedef void(^YJYYSpeedBlock)(CLLocationSpeed speed);


@interface YJYYLocationManager ()<CLLocationManagerDelegate>{
    // 位置管理
    CLLocationManager *_locationManager;
    // 地理反編碼
    CLGeocoder *_geocoder;
}
/** 定位成功block */
@property(nonatomic,copy) YJYYLocationBlock locationBlock;
/** 定位失敗block */
@property(nonatomic,copy) YJYYFailureBlock failureBlock;
/** 反編碼成功block */
@property(nonatomic,copy) YJYYReverseGeoBlock reverseGeoBlcok;
/** 速度變化block */
@property(nonatomic,copy) YJYYSpeedBlock speedBlock;
@end

@implementation YJYYLocationManager

+ (instancetype)sharedManager {
    static id _instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init];
    });
    return _instance;
}

- (instancetype)init {
    if (self = [super init]) {
        _geocoder = [[CLGeocoder alloc] init];
        // 創(chuàng)建管理者
        _locationManager = [[CLLocationManager alloc] init];
        // 設(shè)置代理
        _locationManager.delegate  = self;
        // 設(shè)置定位距離過(guò)濾參數(shù) (當(dāng)本次定位和上次定位之間的距離大于或等于這個(gè)值時(shí)垄分,調(diào)用代理方法)
        _locationManager.distanceFilter  = 100 ;
        // 設(shè)置定位精度(精度越高越耗電)
        [_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
        //版本適配 請(qǐng)求權(quán)限 iOS 8之后必須在plist中添加相應(yīng)key
        if ([_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
            [_locationManager requestWhenInUseAuthorization];
        }
        //判斷是否允許定位
        if ([CLLocationManager locationServicesEnabled]) {
            // 開(kāi)啟實(shí)時(shí)定位
            [_locationManager startUpdatingLocation];
        }
    }
    return self;
}


//獲取用戶(hù)定位
- (void)updateLocationWithLocation:(void (^)(CLLocation *location))locationCB failureCB:(void (^)(NSError *error))failureCB{
    NSAssert(locationCB != nil, @"定位成功回調(diào)不能為空");
    self.locationBlock = locationCB;
    NSAssert(failureCB != nil, @"定位失敗回調(diào)不能為空");
    self.failureBlock = failureCB;
}


//反地理編碼
- (void)reverseGeocodeLocation:(CLLocation *)location callBack:(void(^)(NSString * place))callBack{
    [_geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        CLPlacemark * placemark = placemarks.firstObject;
        if (callBack) {
            callBack(placemark.name);
        }
    }];
}

//獲取定位后再反編碼
- (void)updateReverseGeocodeLocation:(void (^)(NSString *placeName))callBack {
    NSAssert(callBack !=nil, @"反編碼回調(diào)傳入不能為空");
    self.reverseGeoBlcok = callBack;
}

//用戶(hù)速度回調(diào)
- (void)updateSpeedWithCallBack:(void (^)(CLLocationSpeed speed))callBack {
    NSAssert(callBack !=nil, @"速度回調(diào)傳入不能為空");
    self.speedBlock = callBack;
}

//計(jì)算兩坐標(biāo)距離
- (CLLocationDistance)distanceFromCoordinate:(CLLocationCoordinate2D)startCoordinate toTargetCoordinate:(CLLocationCoordinate2D)targetCoordinate {
    CLLocation *curtLocation = [[CLLocation alloc] initWithLatitude:startCoordinate.latitude longitude:startCoordinate.longitude];
    CLLocation *targetLocation = [[CLLocation alloc] initWithLatitude:targetCoordinate.latitude longitude:targetCoordinate.longitude];
    CLLocationDistance distance =  [curtLocation distanceFromLocation:targetLocation];
    return distance/1000.f;
}

//從當(dāng)前位置到目標(biāo)位置距離
- (void)distanceFromCurrentLocationToTargetLocation:(CLLocationCoordinate2D)targetCoordinate callBack:(void (^)(CLLocationDistance))callBack{
    //先獲取定位
    [self updateLocationWithLocation:^(CLLocation *location) {
        if (callBack) {
            callBack([self distanceFromCoordinate:location.coordinate toTargetCoordinate:targetCoordinate]);
        }
    } failureCB:^(NSError *error) {
        NSLog(@"抱歉獲取定位失敗");
    }];
}

#pragma  mark -  代理回調(diào)
#pragma  mark -
/** 獲取到新的位置信息時(shí)調(diào)用*/
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    //去除第一條數(shù)據(jù)
    CLLocation * location = locations.firstObject;
    
    __weak typeof(self) weakSelf = self;
    
    //定位成功回調(diào)
    if (self.locationBlock) {
        self.locationBlock(locations.firstObject);
    }
    
    //反編碼回調(diào)
    if (self.reverseGeoBlcok) {
        [self reverseGeocodeLocation:locations.firstObject callBack:^(NSString *place) {
            weakSelf.reverseGeoBlcok(place);
        }];
    }
    
    //速度回調(diào)
    if (self.speedBlock) {
        self.speedBlock(location.speed *3.6);
    }
}

/** 不能獲取位置信息時(shí)調(diào)用*/
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    if (self.failureBlock) {
        NSLog(@"獲取定位失敗");
        self.failureBlock(error);
    }
}

@end

代碼都有詳細(xì)的注釋 還是很清晰的宛篇,有什么不懂得可以留言

總結(jié)

封裝一個(gè)工具類(lèi),我覺(jué)得核心思想就是明確自己需要的薄湿,然后根據(jù)想要的去定制接口 叫倍,最后想辦法來(lái)實(shí)現(xiàn)需求,當(dāng)然除了作為一個(gè)工具類(lèi)來(lái)說(shuō)豺瘤,就單單返回用戶(hù)定位這一個(gè)方法肯定是不夠的吆倦,我還提供了更加豐富的API在里面例如地理反編碼( 傳入經(jīng)緯度返回地名)、 獲取定位后反編碼之后用戶(hù)位置坐求、 更新速度信息等 具體可以查看代碼或者看我的github地址蚕泽。有需要的可以直接拿去用。哪里寫(xiě)的不好的地方也可以提出更好的建議桥嗤。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末须妻,一起剝皮案震驚了整個(gè)濱河市派任,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌璧南,老刑警劉巖掌逛,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異司倚,居然都是意外死亡豆混,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)动知,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)皿伺,“玉大人,你說(shuō)我怎么就攤上這事盒粮⊥遗福” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵丹皱,是天一觀的道長(zhǎng)妒穴。 經(jīng)常有香客問(wèn)我,道長(zhǎng)摊崭,這世上最難降的妖魔是什么讼油? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮呢簸,結(jié)果婚禮上矮台,老公的妹妹穿的比我還像新娘。我一直安慰自己根时,他們只是感情好瘦赫,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著蛤迎,像睡著了一般确虱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上忘苛,一...
    開(kāi)封第一講書(shū)人閱讀 49,950評(píng)論 1 291
  • 那天蝉娜,我揣著相機(jī)與錄音,去河邊找鬼扎唾。 笑死召川,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的胸遇。 我是一名探鬼主播荧呐,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了倍阐?” 一聲冷哼從身側(cè)響起概疆,我...
    開(kāi)封第一講書(shū)人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎峰搪,沒(méi)想到半個(gè)月后岔冀,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡概耻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年使套,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鞠柄。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡侦高,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出厌杜,到底是詐尸還是另有隱情奉呛,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布夯尽,位于F島的核電站瞧壮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏呐萌。R本人自食惡果不足惜馁痴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望肺孤。 院中可真熱鬧,春花似錦济欢、人聲如沸赠堵。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)茫叭。三九已至,卻和暖如春半等,著一層夾襖步出監(jiān)牢的瞬間揍愁,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工杀饵, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留莽囤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓切距,卻偏偏與公主長(zhǎng)得像朽缎,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,842評(píng)論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)话肖、插件北秽、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,066評(píng)論 4 62
  • 本屆匿名投票榮譽(yù)榜 詩(shī)魁:正云,作品《八聲甘州·望湘淚雨》 副魁(并列): 高十一妹最筒,作品《八聲甘州 南京》 三紳...
    霙愔閱讀 475評(píng)論 0 5
  • 記得剛談戀愛(ài)時(shí)贺氓,就被老公的文才所感染,每天在一起都聽(tīng)他背誦和講解一些古詩(shī)詞床蜘,我那時(shí)在他面前就像一個(gè)小學(xué)生辙培,自己也...
    hesiting閱讀 133評(píng)論 5 4
  • 自由是全世界人都向往的一種狀態(tài),但是我們對(duì)于自由其實(shí)離得很遠(yuǎn)悄泥,也沒(méi)有認(rèn)真思考過(guò)什么是自由虏冻。 “自由...
    朵朵頤閱讀 168評(píng)論 0 0