国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > iOS > 正文

iOS實(shí)現(xiàn)模擬定位功能的示例代碼

2020-07-26 02:18:45
字體:
供稿:網(wǎng)友

前言

App中越來越多的功能依賴用戶實(shí)際的位置,例如基于用戶位置提供推薦數(shù)據(jù)、基于定位判斷某些功能是否可用,但是在開發(fā)調(diào)試中XCode卻沒有提供自定義的模擬定位的功能,所以本文主要的目的是現(xiàn)實(shí)一個可以在開發(fā)調(diào)試過程中隨時模擬定位的功能。

思路

我們在iOS的app開發(fā)中通常采用的是CLLocationManager來獲取用戶當(dāng)前的位置,當(dāng)然也可以采用MKMapView的showUserLocation來獲取用戶的位置,所以我們分別針對這兩種情況分析。

CLLocationManager

采用CLLocationManager獲取定位時,是根據(jù)CLLocationManagerDelegate中- (void)locationManager:(CLLocationManager *)manager   didUpdateLocations:(NSArray<CLLocation *> *)locations的回調(diào)來獲取到定位的。我們只需要在系統(tǒng)回調(diào)這個方法傳遞給業(yè)務(wù)代碼的中間,插入一部分代碼,來修改locations參數(shù)。原本的邏輯為系統(tǒng)回調(diào)->業(yè)務(wù)代碼,現(xiàn)在變?yōu)橄到y(tǒng)回調(diào)->模擬定位模塊->業(yè)務(wù)代碼,就實(shí)現(xiàn)了無侵入式的實(shí)現(xiàn)模擬定位功能。為了實(shí)現(xiàn)這個邏輯,可以有以下幾個思路。

1、 Runtime swizzle

因為業(yè)務(wù)代碼是根據(jù)- (void)locationManager:(CLLocationManager *)manager   didUpdateLocations:(NSArray<CLLocation *> *)locations方法來接受回調(diào)的,所以可以采用Runtime swizzle這個方法,來實(shí)現(xiàn)模擬定位的功能,但是我們中間組件是不知道業(yè)務(wù)代碼中具體是哪個類,所以無法具體指定runtime swizzle哪個類,所以只能遍歷所有的類,判斷當(dāng)前類的方法列表中是否有l(wèi)ocationManager:didUpdateLocations:這個方法,如果存在則swizzle。

  • 優(yōu)點(diǎn):便于理解。
  • 缺點(diǎn):需要遍歷所有的類和類的方法列表。

2、中間代理對象

這種思路是Swizzle了CLLocationManager的setDelegate:方法,當(dāng)調(diào)用setDelegate時,將真實(shí)的delegate object保存下來,再將我們定義的中間代理類swizzle delegate對象設(shè)置為CLLocationManager的delegate,這樣當(dāng)系統(tǒng)回調(diào)CLLocationManagerDelegate,會先回調(diào)到中間代理類swizzle delegate中,再由swizzle delegate將事件傳遞到真實(shí)的delegate object。

  • 優(yōu)點(diǎn):相對于第一種方法,不需要遍歷類和類的方法列表,只需swizzle CLLocationManager中的setDelegate:方法即可。
  • 缺點(diǎn):在中間代理類swizzle delegate中需要實(shí)現(xiàn)全部的CLLocationManagerDelegate方法,如果后續(xù)增加代理方法,仍需要修改這個類。

3、采用NSProxy實(shí)現(xiàn)中間代理對象

Objective-C中有2個基類,常用的就是NSObject,另一個就是NSProxy,NSProxy主要用于消息轉(zhuǎn)發(fā)處理,所以采用NSProxy我們可以更好的處理方法二中的缺點(diǎn)。

3.1創(chuàng)建一個新的類MockLocationProxy,集成自NSProxy。

// MockLocationProxy.h#import <CoreLocation/CoreLocation.h>@interface MockLocationProxy : NSProxy@property (nonatomic, weak, readonly, nullable) id <CLLocationManagerDelegate> target;- (instancetype)initWithTarget:(id <CLLocationManagerDelegate>)target;@end
// MockLocationProxy.m#import "MockLocationProxy.h"@implementation MockLocationProxy- (instancetype)initWithTarget:(id<CLLocationManagerDelegate>)target {  _target = target;  return self;}@end

接著就來處理消息轉(zhuǎn)發(fā)的邏輯,首先我們要知道我們想要的是什么效果,系統(tǒng)回調(diào)給MockLocationProxy,MockLocationProxy只處理locationManager:didUpdateLocations:,其他的消息都仍然交給原target。

所以我們在MockLocationProxy.m中添加以下方法:

// MockLocationProxy.m@implementation MockLocationProxy- (instancetype)initWithTarget:(id<CLLocationManagerDelegate>)target {  _target = target;  return self;}- (BOOL)respondsToSelector:(SEL)aSelector {  if (aSelector == @selector(locationManager:didUpdateLocations:)) {    return YES;  }  return [self.target respondsToSelector:aSelector];}- (void)forwardInvocation:(NSInvocation *)invocation {  SEL sel = invocation.selector;  if ([self.target respondsToSelector:sel]) {    [invocation invokeWithTarget:self.target];  }}- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {  return [self.target methodSignatureForSelector:sel];}#pragma mark - CLLocationManagerDelegate- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {  if ([self.target respondsToSelector:_cmd]) {    // 模擬定位代碼    CLLocation *mockLocation = [[CLLocation alloc] initWithLatitude:39.908722 longitude:116.397499];    locations = @[mockLocation];    [self.target locationManager:manager didUpdateLocations:locations];  }}@end

當(dāng)消息發(fā)送給MockLocationProxy時,判斷當(dāng)前方法是否是locationManager:didUpdateLocations:,如果是,則MockLocationProxy響應(yīng)事件,否則直接傳遞給原本的target。到此已經(jīng)可以隨時處理模擬定位。你只需要在模擬定位的代碼做一些處理,就可以隨時修改定位。

One more.

上述方法雖然可以模擬定位,但是每次修改模擬值都需重新build,那么有沒有辦法在運(yùn)行時隨時修改這個值呢?

LLDebugTool

當(dāng)然可以,你只需要在你的項目中集成LLDebugTool,調(diào)用其中的Location模塊,LLDebugTool提供了一個UI來隨時修改這個模擬值,讓你在調(diào)試時,隨時模擬定位,LLDebugTool仍提供了很多其他的功能,如果你只需要模擬定位的功能,則只需要集成LLDebugTool/Location這個subspec就可以了。

后記

前言說過,定位除了CLLocationManager之外,MKMapView的showUserLocation也可以獲取定位信息,那么如何解決這個問題呢? 你可以在LLDebugTool/Location中查看答案。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 平潭县| 句容市| 永城市| 若尔盖县| 奉贤区| 东莞市| 澄江县| 古蔺县| 全州县| 乳山市| 成武县| 搜索| 遂平县| 大渡口区| 镇雄县| 新疆| 南平市| 天门市| 科技| 平果县| 东莞市| 闽清县| 牙克石市| 静乐县| 夏河县| 神木县| 疏勒县| 乐都县| 惠安县| 玉龙| 平果县| 泰来县| 沧州市| 民县| 西林县| 汤阴县| 乐昌市| 包头市| 万州区| 巫溪县| 伊川县|