簡介
在移動互聯(lián)網(wǎng)時代,移動app能解決用戶的很多生活瑣事顶瞒,比如
周邊:找餐館、找KTV元旬、找電影院等等
導(dǎo)航:根據(jù)用戶設(shè)定的起點(diǎn)和終點(diǎn)榴徐,進(jìn)行路線規(guī)劃,并指引用戶如何到達(dá)
在上述應(yīng)用中匀归,都用到了定位和地圖功能坑资,在iOS開發(fā)中,要想加入這2大功能穆端,必須基于2個框架進(jìn)行開發(fā)
CoreLocation :用于地理定位袱贮,地理編碼,區(qū)域監(jiān)聽等(著重功能實(shí)現(xiàn))
MapKit :用于地圖展示体啰,例如大頭針攒巍,路線、覆蓋層展示等(著重界面展示)
2個熱門專業(yè)術(shù)語
LBS :Location Based Service
SoLoMo :Social Local
Mobile(索羅門)(機(jī)會 社交 位置)
CLLocationManager
CLLocationManager的常用操作
開始更新用戶位置
-(void)startUpdatingLocation;
停止更新用戶位置
-(void) stopUpdatingLocation;
當(dāng)調(diào)用了startUpdatingLocation方法后荒勇,就開始不斷地請求柒莉、刷新用戶的位置,一旦請求到用戶位置就會調(diào)用代理的下面方法
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations;
locations參數(shù)里面裝著CLLocation對象
CLLocationManager補(bǔ)充
為了嚴(yán)謹(jǐn)起見枕屉,最好在使用定位功能之前判斷當(dāng)前應(yīng)用的定位功能是否可用
CLLocationManager有個類方法可以判斷當(dāng)前應(yīng)用的定位功能是否可用
- (BOOL)locationServicesEnabled;
@property(assign, nonatomic) CLLocationDistance
distanceFilter;
每隔多少米定位一次
@property(assign, nonatomic) CLLocationAccuracy
desiredAccuracy;
定位精確度(越精確就越耗電)
CLLocation
CLLocation用來表示某個位置的地理信息常柄,比如經(jīng)緯度鲤氢、海拔等等
@property(readonly, nonatomic) CLLocationCoordinate2D
coordinate;
經(jīng)緯度
@property(readonly, nonatomic) CLLocationDistance
altitude;
海拔
@property(readonly, nonatomic) CLLocationDirection
course;
路線搀擂,航向(取值范圍是0.0°~ 359.9°,0.0°代表真北方向)
@property(readonly, nonatomic) CLLocationSpeed speed;
移動速度(單位是m/s)
用- (CLLocationDistance)distanceFromLocation:(const CLLocation*)location方法可以計算2個位置之間的距離
iOS 8.0+ 的定位適配
從iOS 8.0開始卷玉,蘋果進(jìn)一步加強(qiáng)了對用戶隱私的保護(hù)哨颂。
當(dāng)APP想訪問用戶的隱私信息時,系統(tǒng)不再自動彈出一個對話框讓用戶授權(quán)
解決方案:
(1)調(diào)用iOS 8.0的API相种,主動請求用戶授權(quán)
(void)requestAlwaysAuthorization 請求允許在前后臺都能獲取用戶位置的授權(quán)
(void)requestWhenInUseAuthorization 請求允許在前臺獲取用戶位置的授權(quán)
(2)務(wù)必在info.plist文件中配置對應(yīng)的鍵值威恼, 否則以上請求授權(quán)的方法不生效
NSLocationAlwaysUsageDescription : 允許在前后臺獲取GPS的描述
NSLocationWhenInUseDescription : 允許在前臺獲取GPS的描述
iOS 9.0 定位補(bǔ)充
iOS 9.0 如果當(dāng)前處于前臺授權(quán)狀態(tài),默認(rèn)是不可以后臺獲取用戶位置。但可以設(shè)置以下屬性為YES箫措,就可以繼續(xù)獲取后臺位置腹备,但是會出現(xiàn)藍(lán)條
@property(assign, nonatomic) BOOL
allowsBackgroundLocationUpdates
使用注意:必須設(shè)置打開對應(yīng)的后臺模式:location updates
iOS 9.0 可以單次請求用戶位置
- (void)requestLocation
-(void)locationManager:(nonnull CLLocationManager
*)manager didUpdateLocations:(nonnull NSArray<CLLocation *>
*)locations 成功調(diào)用
-(void)locationManager:(nonnull CLLocationManager *)manager
didFailWithError:(nonnull NSError *)error
失敗調(diào)用
CLLocationCoordinate2D
CLLocationCoordinate2D是一個用來表示經(jīng)緯度的結(jié)構(gòu)體,定義如下
typedef struct {
CLLocationDegreeslatitude; 緯度
CLLocationDegreeslongitude; 經(jīng)度
}
CLLocationCoordinate2D;
一般用CLLocationCoordinate2DMake函數(shù)來創(chuàng)建CLLocationCoordinate2D
CLGeocoder
使用CLGeocoder可以完成“地理編碼”和“反地理編碼”
地理編碼:根據(jù)給定的地名斤蔓,獲得具體的位置信息(比如經(jīng)緯度植酥、地址的全稱等)
反地理編碼:根據(jù)給定的經(jīng)緯度,獲得具體的位置信息
地理編碼方法
-(void)geocodeAddressString:(NSString *)addressString completionHandler:(CLGeocodeCompletionHandler)completionHandler;
反地理編碼方法
- (void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler;
CLGeocodeCompletionHandler
當(dāng)?shù)乩韁反地理編碼完成時弦牡,就會調(diào)用CLGeocodeCompletionHandler
typedef void (^CLGeocodeCompletionHandler)(NSArray *placemarks, NSError *error);
這個block傳遞2個參數(shù)
error :當(dāng)編碼出錯時(比如編碼不出具體的信息)有值
place marks :里面裝著CLPlacemark對象
CLPlacemark
CLPlacemark的字面意思是地標(biāo)友驮,封裝詳細(xì)的地址位置信息
@property (nonatomic, readonly) CLLocation *location;
地理位置
@property (nonatomic, readonly) CLRegion *region; 區(qū)域
@property (nonatomic, readonly) NSDictionary *addressDictionary;
詳細(xì)的地址信息
@property (nonatomic, readonly) NSString *name;
地址名稱
@property (nonatomic, readonly) NSString *locality; 城市
*************************筆記**************************
一. iOS8.0之前的定位(?????)
iOS8特性:
1.iOS8.0+前后臺的定位授權(quán)描述
NSLocationAlwaysUsageDescription
2.iOS8.0前-定位描述
Privacy
- Location Usage Description
3.iOS8.0+前臺定位授權(quán)描述
NSLocationWhenInUseUsageDescription
4.在iOS8.0之后是前臺定位,那么當(dāng)APP退到后臺時,屏幕頂部會出現(xiàn)藍(lán)條
5.不需要勾選后臺模式,也可以進(jìn)行后臺定位
注意:此時授權(quán)狀態(tài)如果是前后臺定位,那么當(dāng)APP退到后臺時,屏幕頂部不會出現(xiàn)藍(lán)條
iOS9:
注意:
1.如果在iOS9.0,如果在前臺定位授權(quán)狀態(tài)下,(想要在后臺也獲取用戶位置),不但要勾選后臺模式Location
Updates,還要做以下設(shè)置:_locationM.allowsBackgroundLocationUpdates= YES;
2.此時授權(quán)狀態(tài)如果是前后臺定位,那么當(dāng)APP退到后臺時,屏幕頂部不會出現(xiàn)藍(lán)條
如果授權(quán)狀態(tài)為前臺定位,那么當(dāng)APP退到后臺時,屏幕同樣會出現(xiàn)藍(lán)條
- 前臺定位
CoreLocation框架
一. iOS8.0之前的定位(?????)
- 前臺定位
- 導(dǎo)入CoreLocation框架以及對應(yīng)的主頭文件
import <CoreLocation/CoreLocation.h>
- 創(chuàng)建CLLocationManager對象并設(shè)置代理
self.locationM = [[CLLocationManager alloc] init];
self.locationM.delegate = self;
- 調(diào)用方法,開始更新用戶位置信息
[self.locationM startUpdatingLocation];
- 在對應(yīng)的代理方法中獲取位置信息
-(void)locationManager:(nonnull
CLLocationManager *)manager didUpdateLocations:(nonnull
NSArray<CLLocation > *)locations
{
NSLog(@"每當(dāng)請求到位置信息時, 都會調(diào)用此方法");
}
后臺定位
在前臺定位基礎(chǔ)上,
勾選后臺模式Location updates
額外設(shè)置
每隔多少米定位一次
代碼: self.locationM.distanceFilter = 100;
功能: 只有當(dāng)最新的位置與上一次獲取的位置之間的距離, 大于這個值時, 才會通過代理告訴外界
- 設(shè)置定位精確度
代 碼: self.locationM.desiredAccuracy = kCLLocationAccuracyBest;
功 能: 通過設(shè)置此屬性, 獲取不同精確度的位置信息
注意事項(xiàng): 精確度越高,越耗電驾锰,定位所需時間越長
枚舉注解:
|
枚舉值 | 含義
|
------------ |
---|
|
kCLLocationAccuracyBestForNavigation | 最適合導(dǎo)航 |
|
kCLLocationAccuracyBest | 精度最好的 |
|
kCLLocationAccuracyNearestTenMeters | 附近10米
|
|
kCLLocationAccuracyHundredMeters | 附近100米|
|
kCLLocationAccuracyKilometer | 附近1000米 |
|
kCLLocationAccuracyThreeKilometers | 附近3000米 |
- 知識補(bǔ)充
- 定位常識
- 標(biāo)準(zhǔn)定位服務(wù)(基于gps/基站/wifi定位, 具體使用哪種,蘋果有自己規(guī)則)
程序關(guān)閉,就沒法獲取位置
- 顯著的位置變化定位服務(wù)(使用基站進(jìn)行定位,所以必須要求設(shè)備有電話模塊)
當(dāng)app被完全關(guān)閉時,也可以接收到位置通知,并讓app進(jìn)入到后臺處理
定位精度相比于上面,精度不大,所以耗電小,而且定位更新頻率依據(jù)基站密度而定
- 應(yīng)用場景
如果要求定位及時,精度較高,并且運(yùn)行時間較短,可使用標(biāo)準(zhǔn)定位;
如果長時間監(jiān)控用戶位置,用戶移動速度比較快(例如打車軟件),可使用后者
測試環(huán)境:
XCode7.0之前版本,例如XCode6.4版本
- 模擬器選擇iOS8.0之前的版本
- 原因 :
XCode7.0(包含7.0)之后不支持iOS8.0之前的模擬器
常見問題總結(jié)
定位不到, 對應(yīng)的代理方法不執(zhí)行
首先,檢查運(yùn)行的模擬器是否是iOS8.0之前的系統(tǒng)版本
其次,檢查模擬器是否設(shè)置位置數(shù)據(jù)
第三,確保代碼無問題(一般都是代理沒有設(shè)置,或者位置管理器對象是局部變量,亦或是位置管理器對象沒有被強(qiáng)引用)
第四,絕逼是模擬器BUG, 請重置模擬器(是重置,不是重啟)
二. iOS8.0之后定位(?????)
- 前臺定位
- 導(dǎo)入CoreLocation框架以及對應(yīng)的主頭文件
import <CoreLocation/CoreLocation.h>
- 創(chuàng)建CLLocationManager對象并設(shè)置代理
self.locationM = [[CLLocationManager alloc] init];
self.locationM.delegate = self;
- 請求前臺定位授權(quán),
并在Info.Plist文件中配置Key(Nslocationwheninuseusagedescription)
在前后臺都可以獲取用戶位置信息, 無論是否勾選后臺模式
[self.locationM requestWhenInUseAuthorization];
- 調(diào)用方法,開始更新用戶位置信息
[self.locationM startUpdatingLocation];
- 在對應(yīng)的代理方法中獲取位置信息
-(void)locationManager:(nonnull
CLLocationManager *)manager didUpdateLocations:(nonnull
NSArray<CLLocation > *)locations
{
NSLog(@"每當(dāng)請求到位置信息時, 都會調(diào)用此方法");
}
后臺定位
方案一:在前臺定位基礎(chǔ)上,
勾選后臺模式Location updates
注意:此時授權(quán)狀態(tài)如果是前臺定位, 那么當(dāng)APP退到后臺時, 屏幕頂部會出現(xiàn)藍(lán)條
方案二:
- 請求前后臺定位授權(quán),并在info.plist文件中配置KEY NSLocationWhenInUseUsageDescription iOS8.0+前臺定位授權(quán)描述
[self.locationM requestAlwaysAuthorization];
注意:不需要勾選后臺模式, 也可以進(jìn)行后臺定位
注意:此時授權(quán)狀態(tài)如果是前后臺定位, 那么即使APP退到后臺時, 屏幕頂部會也不會出現(xiàn)藍(lán)條
監(jiān)聽用戶授權(quán)狀態(tài)
實(shí)現(xiàn)以下代理方法即可
表示當(dāng)前應(yīng)用程序的授權(quán)狀態(tài)卸留。
(CLAuthorizationStatus)status
當(dāng)用戶授權(quán)狀態(tài)發(fā)生變化時調(diào)用
-(void)locationManager:(nonnull
CLLocationManager *)manager
didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
用戶還未決定
case
kCLAuthorizationStatusNotDetermined:
{
NSLog(@"用戶還未決定");
break;
}
訪問受限(蘋果預(yù)留選項(xiàng),暫時沒用)
case
kCLAuthorizationStatusRestricted:
{
NSLog(@"訪問受限");
break;
}
定位關(guān)閉時和對此APP授權(quán)為never時調(diào)用
case kCLAuthorizationStatusDenied:
{
定位是否可用(是否支持定位或者定位是否開啟)
if([CLLocationManager
locationServicesEnabled])
{
NSLog(@"定位開啟,但被拒");
在此處, 應(yīng)該提醒用戶給此應(yīng)用授權(quán),
并跳轉(zhuǎn)到"設(shè)置"界面讓用戶進(jìn)行授權(quán)
在iOS8.0之后跳轉(zhuǎn)到"設(shè)置"界面代碼
NSURL *settingURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
if([[UIApplication
sharedApplication] canOpenURL:settingURL])
{
[[UIApplication sharedApplication] openURL:settingURL];
}
}else
{
NSLog(@"定位關(guān)閉椭豫,不可用");
}
break;
}
獲取前后臺定位授權(quán)
case
kCLAuthorizationStatusAuthorizedAlways:
case kCLAuthorizationStatusAuthorized: 失效耻瑟,不建議使用
{
NSLog(@"獲取前后臺定位授權(quán)");
break;
}
獲得前臺定位授權(quán)
case
kCLAuthorizationStatusAuthorizedWhenInUse:
{
NSLog(@"獲得前臺定位授權(quán)");
break;
}
default:
break;
}
}
測試環(huán)境:
XCode版本無要求
模擬器選擇iOS8.0之后的版本
常見問題總結(jié)
定位不到, 對應(yīng)的代理方法不執(zhí)行
首先,檢查是否請求授權(quán), 并設(shè)置了對應(yīng)的KEY
其次,檢查模擬器是否設(shè)置位置數(shù)據(jù)
第三,確保代碼無問題(一般都是代理沒有設(shè)置,或者位置管理器對象是局部變量,亦或是位置管理器對象沒有被強(qiáng)引用)
第四,絕逼是模擬器BUG, 請重置模擬器(是重置,不是重啟)
三. iOS9.0 定位補(bǔ)充(???)
- 定位變化
- 前臺定位
(同iOS8.0之后一致, 無任何變化,
都需要主動請求授權(quán))
- 后臺定位
方案一:
- 在前臺定位基礎(chǔ)上,
勾選后臺模式Location updates, 并且設(shè)置以下屬性為YES
if ([[UIDevice currentDevice].systemVersion
floatValue] >= 9.0)
{
一個布爾值,該值指示是否應(yīng)用程序想要接收位置更新時暫停赏酥。
self.locationM.allowsBackgroundLocationUpdates
= YES;
}
方案二:
- 請求前后臺定位授權(quán),并在info.plist文件中配置KEY ( NSLocationAlwaysUsageDescription )
[self.locationM requestAlwaysAuthorization];
新的API
單次定位請求;
代 碼: [self.locationM requestLocation];
功 能: 獲取一次位置信息
實(shí)現(xiàn)邏輯:
(1) 按照定位精確度從低到高進(jìn)行排序匆赃,逐個進(jìn)行定位.如果在有效時間內(nèi), 定位到了精確度最好的位置, 那么就把對應(yīng)的位置通過代理告知外界.
(2) 如果獲取到的位置不是精確度最高的那個,也會在定位超時后今缚,通過代理告訴外界.
注意事項(xiàng):
(1) 必須實(shí)現(xiàn)代理的-locationManager:didFailWithError:方法
(2) 不能與startUpdatingLocation方法同時使用
測試環(huán)境:
XCode版本要求7.0版本以上
模擬器選擇iOS9.0之后的版本
常見問題總結(jié)
單次定位在模擬器上測試不出效果?
答: 因?yàn)槟M器的位置是固定的, 所以無法測試出效果, 請使用真機(jī)進(jìn)行測試.
四. CLLocation對象詳解(?????)
- 屬性解釋
coordinate : 當(dāng)前位置所在的經(jīng)緯度數(shù)據(jù)
altitude : 海拔
speed : 當(dāng)前速度
course : 航向(設(shè)備移動的方向, 值域范圍:0.0 ~ 259.9, 正北方向?yàn)?.0)
- 重要方法
代碼: -
(CLLocationDistance)distanceFromLocation:(CLLocation *)location
作用: 計算兩個位置對象之間的物理距離, 單位是(米)
場景演練
場景演示:打印當(dāng)前用戶的行走方向,偏離角度以及對應(yīng)的行走距離,
例如:”北偏東30度方向,移動了8米”
- 實(shí)現(xiàn)步驟:
1> 獲取對應(yīng)的方向偏向(例如”正東”,”東偏南”)
2> 獲取對應(yīng)的偏離角度(并判斷是否是正方向)
3> 計算行走距離
4> 打印信息
注意事項(xiàng)
使用位置前,
務(wù)必判斷當(dāng)前獲取的位置是否有效
代碼: if(location.horizontalAccuracy < 0) return;
功能: 如果水平精確度小于零, 代表雖然可以獲取位置對象, 但是數(shù)據(jù)錯誤, 不可用
經(jīng)驗(yàn)小結(jié)(??)
一. 定位的應(yīng)用場景
導(dǎo)航
電商APP,獲取用戶所在城市(需要與(反)地理編碼聯(lián)合使用)
數(shù)據(jù)采集用戶信息(例如,統(tǒng)計app使用分布)
查找周邊(周邊好友, 周邊商家等等)
二. 開發(fā)經(jīng)驗(yàn)
** 由于定位非常耗電;
所以為了給用戶省電, 你可以遵守以下小經(jīng)驗(yàn)**
1)不需要獲取用戶位置時,一定要關(guān)閉定位服務(wù):
2)如果能滿足項(xiàng)目需求,盡可能的使用”監(jiān)聽顯著位置變化”的定位服務(wù)(打車app)
3)如果可以,盡可能使用低精度的desiredAccuracy
4)如果是數(shù)據(jù)采集,(一般都是周期性的去輪詢用戶位置),在輪詢期間一定要關(guān)閉定位
五. 指南針效果實(shí)現(xiàn)(??)
實(shí)現(xiàn)思路
利用"磁力計"傳感器,獲取設(shè)備朝向
根據(jù)設(shè)備朝向反向旋轉(zhuǎn)"指南針"圖片
代碼實(shí)現(xiàn)
獲取設(shè)備朝向
- 導(dǎo)入CoreLocation框架以及對應(yīng)的主頭文件
import <CoreLocation/CoreLocation.h>
- 創(chuàng)建CLLocationManager對象并設(shè)置代理
self.locationM = [[CLLocationManager alloc] init];
self.locationM.delegate = self;
- 調(diào)用方法, 開始獲取設(shè)備朝向
[self.locationM startUpdatingHeading];
- 在對應(yīng)的代理方法中獲取設(shè)備朝向信息
-(void)locationManager:(CLLocationManager *)manager
didUpdateHeading:(CLHeading *)newHeading
{
旋轉(zhuǎn)圖片代碼
}
- 旋轉(zhuǎn)圖片
1.判斷當(dāng)前的角度是否有效(如果此值小于0,代表角度無效)
if(newHeading.headingAccuracy < 0)
return;
2.獲取當(dāng)前設(shè)備朝向(磁北方向)
CGFloat angle =
newHeading.magneticHeading;
3.轉(zhuǎn)換成為弧度
CGFloat radian = angle
/ 180.0 * M_PI;
4.帶動畫反向旋轉(zhuǎn)指南針
[UIView
animateWithDuration:0.5 animations:^{
self.compassView.transform =
CGAffineTransformMakeRotation(-radian);
}];
- 概念補(bǔ)充
磁北角度: newHeading.magneticHeading ------- 相對于"磁北方向"產(chǎn)生的角度
真北角度: newHeading.trueHeading ------- 相對于"真北方向"產(chǎn)生的角度
注意事項(xiàng)
獲取設(shè)備朝向前,
先判斷"磁力計"是否可用
[CLLocationManager
headingAvailable];
- 獲取朝向前,
判斷當(dāng)前朝向信息是否有效
if(newHeading.headingAccuracy < 0)return;
- 注意與"航向"的區(qū)別
設(shè)備朝向是指手機(jī)的朝向; "航向"可以理解為設(shè)備的移動方向
- 使用"磁力計"傳感器獲取設(shè)備朝向, 不需要請求用戶授權(quán)
因?yàn)樵O(shè)備朝向不涉及用戶隱私
5.測試環(huán)境
XCode版本無要求(建議:XCode7.0不需要開發(fā)者賬號也可以進(jìn)行真機(jī)調(diào)試)
必須要求真機(jī)設(shè)備(只有真機(jī)設(shè)備才有"磁力計"傳感器)
六. 區(qū)域監(jiān)聽(???)
1.概念解釋
區(qū) 域: 就是指劃定的一塊地域范圍(比如圓形區(qū)域, 則由區(qū)域中心, 和半徑組成)
區(qū)域監(jiān)聽: 是指,我們通過代碼指定一個區(qū)域, 然后當(dāng)用戶持握設(shè)備進(jìn)入或者離開指定區(qū)域, 我們都能監(jiān)聽到.
- 監(jiān)聽指定區(qū)域
- 導(dǎo)入CoreLocation框架以及對應(yīng)的主頭文件
import <CoreLocation/CoreLocation.h>
- 創(chuàng)建CLLocationManager對象并設(shè)置代理
self.locationM = [[CLLocationManager alloc] init];
self.locationM.delegate = self;
- 請求前后臺定位,
或前臺定位授權(quán), 并在Info.Plist文件中配置相應(yīng)的Key
[self.locationM requestAlwaysAuthorization];
[self.locationM
requestWhenInUseAuthorization];
- 創(chuàng)建一個區(qū)域,
并開始監(jiān)聽
- 判斷區(qū)域監(jiān)聽服務(wù)是否可用(定位服務(wù)是否關(guān)閉, 定位是否授權(quán), 是否開啟飛行模式)
if ([CLLocationManager
isMonitoringAvailableForClass:[CLCircularRegion class]])
{
創(chuàng)建區(qū)域中心
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(29.12345,
131.23456);
創(chuàng)建區(qū)域(指定區(qū)域中心算柳,和區(qū)域半徑)
CLLocationDistance radius = 1000;
判斷區(qū)域半徑是否大于最大監(jiān)聽區(qū)域半徑,如果大于, 就沒法監(jiān)聽
if (radius > self.locationM.maximumRegionMonitoringDistance)
{
radius = self.locationM.maximumRegionMonitoringDistance;
}
CLCircularRegion *region = [[CLCircularRegion alloc]
initWithCenter:center radius:radius identifier:@"小碼哥"];
開始監(jiān)聽指定區(qū)域
[self.locationM startMonitoringForRegion:region];
}
else
{
NSLog(@"區(qū)域監(jiān)聽不可用");
}
- 在對應(yīng)的代理方法中監(jiān)聽區(qū)域狀態(tài)
進(jìn)去監(jiān)聽區(qū)域后調(diào)用(調(diào)用一次)
-(void)locationManager:(nonnull
CLLocationManager *)manager didEnterRegion:(nonnull
CLRegion *)region
{
NSLog(@"進(jìn)入?yún)^(qū)域---%@", region.identifier);
[manager
stopMonitoringForRegion:region];
}
離開監(jiān)聽區(qū)域后調(diào)用(調(diào)用一次)
-(void)locationManager:(nonnull
CLLocationManager *)manager didExitRegion:(nonnull
CLRegion *)region
{
NSLog(@"離開區(qū)域---%@", region.identifier);
}
- 獲取某個區(qū)域的當(dāng)前狀態(tài)
監(jiān)聽某個區(qū)域時,
只有進(jìn)入或者離開這個區(qū)域時, 才能回調(diào)對應(yīng)的方法, 是一個進(jìn)入或者離開的動作
如果想知道某一個區(qū)域的當(dāng)前狀態(tài)(識別用戶是在區(qū)域內(nèi)部, 還是區(qū)域外部), 則需要使用以下方法
代 碼:
[self.locationM requestStateForRegion:region];
回調(diào)代理:
請求某個區(qū)域狀態(tài)時, 回調(diào)的代理方法
-(void)locationManager:(CLLocationManager *)manager
didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
switch (state) {
case CLRegionStateUnknown:
NSLog(@"未知狀態(tài)");
break;
case CLRegionStateInside:
NSLog(@"在區(qū)域內(nèi)部");
break;
case CLRegionStateOutside:
NSLog(@"在區(qū)域外部");
break;
default:
break;
}
}
- 測試環(huán)境
XCode版本無要求
iOS模擬器版本無要求
注意事項(xiàng)
想要做區(qū)域監(jiān)聽,
在iOS8.0之后, 必須請求位置授權(quán)
代碼: [self.locationM requestAlwaysAuthorization];
原因: 區(qū)域監(jiān)聽的原理就是獲取用戶的位置, 然后在判斷該位置是否在制定區(qū)域內(nèi), 所以會涉及到用戶隱私(位置), 而在iOS8.0之后, 想要訪問用戶位置信息, 就需要主動請求授權(quán);
- 使用前, 先判斷區(qū)域監(jiān)聽是否可用
代碼: [CLLocationManager
isMonitoringAvailableForClass:[CLCircularRegion class]]
- 注意區(qū)域半徑是否大于最大區(qū)域監(jiān)聽半徑(如果大于, 則無法監(jiān)聽成功)
代碼: radius > self.locationM.maximumRegionMonitoringDistance
常見問題
區(qū)域監(jiān)聽, 測試沒有效果?
首先, 確定代碼沒有問題, 是否有請求授權(quán);
其次, 嘗試修改模擬器位置信息, 觸發(fā)進(jìn)入?yún)^(qū)域或離開區(qū)域的動作
第三, 如果模擬器出現(xiàn)BUG, 定位不到, 也會無法判定當(dāng)前區(qū)域狀態(tài); 所以, 最后可以嘗試重置模擬器.
七. (反)地理編碼(?????)
- 概念解釋
地理編碼: 是指根據(jù)地址關(guān)鍵字, 將其轉(zhuǎn)換成為對應(yīng)的經(jīng)緯度等信息;
發(fā)地理編碼: 是指根據(jù)經(jīng)緯度信息, 將其轉(zhuǎn)換成為對應(yīng)的省市區(qū)街道等信息;
地理編碼
導(dǎo)入CoreLocation框架以及對應(yīng)的主頭文件
import <CoreLocation/CoreLocation.h>
- 創(chuàng)建CLGeocoder對象
self.geoC = [[CLGeocoder alloc] init];
- 根據(jù)地址關(guān)鍵字,
進(jìn)行地理編碼
直接根據(jù)地址進(jìn)行地理編碼(返回結(jié)果可能有多個,因?yàn)橐粋€地點(diǎn)有重名)
[self.geoC geocodeAddressString:@"廣州" completionHandler:^(NSArray<CLPlacemark *> * __nullableplacemarks, NSError * __nullable error)
{
包含區(qū)姓言,街道等信息的地標(biāo)對象
CLPlacemark *placemark = [placemarks firstObject];
城市名稱
NSString *city = placemark.locality;
街道名稱
NSString *street = placemark.thoroughfare;
全稱
NSString *name = placemark.name;
}];
反地理編碼
導(dǎo)入CoreLocation框架以及對應(yīng)的主頭文件
import <CoreLocation/CoreLocation.h>
- 創(chuàng)建CLGeocoder對象
self.geoC = [[CLGeocoder alloc] init];
- 根據(jù)經(jīng)緯度信息,
進(jìn)行反地理編碼
根據(jù)經(jīng)緯度信息進(jìn)行反地理編碼
[self.geoC reverseGeocodeLocation:[[CLLocation
alloc] initWithLatitude:21.123 longitude:123.345]
completionHandler:^(NSArray<CLPlacemark *> * __nullable
placemarks, NSError * __nullable error)
{
包含區(qū)瞬项,街道等信息的地標(biāo)對象
CLPlacemark *placemark = [placemarks firstObject];
城市名稱
NSString *city = placemark.locality;
街道名稱
NSString *street = placemark.thoroughfare;
全稱
NSString *name = placemark.name;
}];
CLPlacemark 地標(biāo)對象詳解
location
: CLLocation 類型, 位置對象信息, 里面包含經(jīng)緯度, 海拔等等
region :
CLRegion 類型, 地標(biāo)對象對應(yīng)的區(qū)域
addressDictionary
: NSDictionary 類型, 存放街道,省市等信息
name :
NSString 類型, 地址全稱
thoroughfare
: NSString 類型, 街道名稱
locality
: NSString 類型, 城市名稱
administrativeArea
: NSString 類型, 省名稱
country
: NSString 類型, 國家名稱
- 測試環(huán)境
- 必須聯(lián)網(wǎng)
XCode版本不限
iOS模擬器系統(tǒng)版本不限
常見問題
測試無數(shù)據(jù)?
首先, 檢查是否有聯(lián)網(wǎng);
其次, 如果是反地理編碼,可嘗試更換經(jīng)緯度再次嘗試, 有的經(jīng)緯度沒有對應(yīng)信息
應(yīng)用場景
一般與定位結(jié)合使用, 確定當(dāng)前位置的具體地理信息
八. 使用第三方框架進(jìn)行定位(??)
- 主要原因
因?yàn)槭褂肅oreLocation框架進(jìn)行獲取用戶位置信息, 是通過代理進(jìn)行回調(diào); 而第三方框架將"代理模擬"轉(zhuǎn)換成為"block模式"; 使用起來比較方便, 而且額外增加了超時時間等功能.
- 框架信息
名稱: locationManager
地址:
link
- 使用方法
參照該框架對應(yīng)的readME
- 注意事項(xiàng)
一般集成第三方框架到項(xiàng)目中, 請先確保該框架沒有問題, 然后再向項(xiàng)目中集成
九. 補(bǔ)充(???)
1. 代理模式到block模式的轉(zhuǎn)換
主要思想就是,先記錄下外界傳遞過來的block, 然后在對應(yīng)的代理方法里面執(zhí)行這個block;