iOS中的定位功能
CoreLocation框架(CoreLocation.framework)可用于定位設(shè)備當(dāng)前的經(jīng)緯度薪前,通過(guò)該框架,應(yīng)用程序可通過(guò)附近的蜂窩基站苍狰、WIFI信號(hào)或者GPS等信息計(jì)算用戶位置露筒。
iOS SDK提供了CLLocationManager、CLLocationManagerDelegate來(lái)處理設(shè)備的定位信息废酷,包括獲取設(shè)備的方向以及進(jìn)行方向檢測(cè)等瘟檩。
iOS開(kāi)發(fā)者使用CoreLocation.framework框架進(jìn)行定位非常簡(jiǎn)單,CoreLocation框架的常用API主要有如下幾個(gè):
- CLLocationManager:定位管理器類澈蟆;
- CLLocationManagerDelegate:該協(xié)議代表定位管理器的delegate協(xié)議墨辛。實(shí)現(xiàn)該協(xié)議的對(duì)象可負(fù)責(zé)處理CLLocationManager的定位事件;
- CLLocation:該對(duì)象代表位置趴俘。該對(duì)象包含了當(dāng)前設(shè)備的經(jīng)度睹簇、緯度、高度寥闪、速度太惠、路線等信息,還包含了該定位信息的水平精確度疲憋、垂直精確度以及時(shí)間戳信息凿渊;
- CLHeading:該對(duì)象代表設(shè)備的移動(dòng)方向;
- CLRegion:該對(duì)象代表一個(gè)區(qū)域缚柳。一般程序不會(huì)直接使用該類埃脏,而是使用它的兩個(gè)子類,即CLCircularRegion(圓形區(qū)域)和CLBeaconRegion(藍(lán)牙信號(hào)區(qū))喂击;
除此之外剂癌,CoreLocation框架還涉及一個(gè)CLLocationCoordinate2D結(jié)構(gòu)體變量,該結(jié)構(gòu)體變量包含經(jīng)度翰绊、緯度兩個(gè)值佩谷,其中CLLocation對(duì)象的coordinate屬性就是一個(gè)CLLocationCoordinate2D結(jié)構(gòu)體變量旁壮。
通過(guò)上述API不難看出,通過(guò)定位我們可以做什么?
- 獲取用戶當(dāng)前位置,記錄路線軌跡等
- 監(jiān)控行車速度和行車距離
- 方向監(jiān)測(cè)
- 指南針
- 區(qū)域監(jiān)聽(tīng),比如用戶進(jìn)入某個(gè)區(qū)域時(shí)推廣某些信息,考勤打卡等
1.定位常用屬性和方法
1.0請(qǐng)求定位步驟
- 導(dǎo)入CoreLocation框架
- 懶加載CLLocationManager對(duì)象
- 請(qǐng)求授權(quán) (1) 使用期間whenInUse (2) 始終允許always
- 注意:必須把授權(quán)對(duì)應(yīng)的key值 添加到info.plist文件中
- 設(shè)置代理,實(shí)現(xiàn)代理方法
- 開(kāi)始定位
1.1獲取定位權(quán)限
定位屬于用戶的隱私權(quán)限,所以當(dāng)APP需要使用這一權(quán)限的時(shí)候,需要獲取用戶的授權(quán).
在獲取授權(quán)之前,我們必須把授權(quán)對(duì)應(yīng)的key值 添加到info.plist文件中,否則可能會(huì)引起APP crash或者審核不通過(guò).
跟定位相關(guān)的隱私權(quán)限主要有兩種,
- NSLocationWhenInUseUsageDescription(使用期間)
- NSLocationAlwaysUsageDescription(始終允許)
通俗的說(shuō),如果只是一次性定位,不需要持續(xù)定位的話,這倆實(shí)際并無(wú)區(qū)別.
而持續(xù)定位時(shí)這倆的差別,會(huì)單獨(dú)在后面講后臺(tái)持續(xù)定位的時(shí)候提及.
1.2定位屬性的應(yīng)用
精確度desiredAccuracy
desiredAccuracy精確度越高,越耗電,屬性接收double類型的值,也可以傳系統(tǒng)給定好的值
系統(tǒng)給出的枚舉類型有以下:
- kCLLocationAccuracyBestForNavigation: 導(dǎo)航精確度(最精確)
- kCLLocationAccuracyBest: 最好精確度(默認(rèn))
- kCLLocationAccuracyNearestTenMeters: 10米的誤差
- kCLLocationAccuracyHundredMeters: 100米的誤差
- kCLLocationAccuracyKilometer: 千米誤差
- kCLLocationAccuracyThreeKilometers: 三千米的誤差
距離過(guò)濾distanceFilter
設(shè)置用于移動(dòng)多少距離,重新進(jìn)行定位
枚舉類型同精確度,也是一個(gè)float值.
1.3位置信息的獲取
通過(guò)代理方法,我們可以獲取到更新后的位置信息.以下是位置具體屬性的圖示.
1.3后臺(tái)持續(xù)定位
之前產(chǎn)品提了一個(gè)需求,想持續(xù)上報(bào)司導(dǎo)的位置信息,這就需要用到我們的后臺(tái)持續(xù)定位功能了.
使用后臺(tái)定位需要以下設(shè)置:
- 選中target-->Gapability,打開(kāi)Background Modes模式谐檀,并勾選Location updates,如下圖所示:
- 設(shè)置允許后臺(tái)更新位置的屬性.需注意的是,該屬性必須和上一條設(shè)置配合使用,否則會(huì)crash
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"9.0")) {
// 該模式是抵抗程序在后臺(tái)被殺抡谐,申明不能夠被暫停
self.locationManager.allowsBackgroundLocationUpdates = YES;
}
self.locationManager.pausesLocationUpdatesAutomatically = NO;
為什么要進(jìn)行以上設(shè)置呢?
因?yàn)閕OS系統(tǒng)下,當(dāng)APP進(jìn)入后臺(tái)時(shí),過(guò)三分鐘之后,APP會(huì)自動(dòng)進(jìn)入掛起模式,也就是說(shuō)如果不做任何處理的情況下,定位會(huì)被系統(tǒng)終止掉.當(dāng)用戶再進(jìn)入APP的時(shí)候,定位又重新開(kāi)始.所以才說(shuō)APP使用定位的授權(quán)選項(xiàng),使用應(yīng)用期間和始終其實(shí)區(qū)別不大.如果不想被終止,就得通過(guò)后臺(tái)模式設(shè)置,向蘋(píng)果聲明,APP在后臺(tái)需要操作的權(quán)限,這樣定位功能才得以保留.
使用定位的授權(quán)選項(xiàng),使用應(yīng)用期間和始終,唯一的區(qū)別就是,當(dāng)APP退到后臺(tái)并持續(xù)定位時(shí),使用應(yīng)用期間的權(quán)限下,APP頂部狀態(tài)欄會(huì)有個(gè)藍(lán)色的條,提示用戶當(dāng)前APP一直在使用定位.而始終這個(gè)選項(xiàng)則不會(huì).
說(shuō)到這里,之前GAPP按照以上設(shè)置,功能正常,但是在提交appstore的時(shí)候被拒絕了,理由是,審核人員不認(rèn)為我們的APP需要持續(xù)定位.后來(lái)在筆者申訴加重新提審的情況下,蘋(píng)果體諒的給我們通過(guò)了.
持續(xù)定位優(yōu)化方案,可以從以下幾個(gè)維度考慮:
- 精度
- 過(guò)濾距離范圍
- 定時(shí)
- 重大位置變化比如方向等
耗電測(cè)試:
1.位置相對(duì)固定時(shí),自動(dòng)更新位置和交替精度(精度非常精確和寬泛時(shí)定時(shí)切換)的對(duì)比實(shí)驗(yàn);
2.位置更新比較頻繁情況下,二者的對(duì)比
第一種情況下,自動(dòng)更新位置能堅(jiān)持8個(gè)小時(shí)左右,交替精度大概在6小時(shí);
第二種情況下,由于位置變動(dòng)時(shí)間只在一個(gè)小時(shí)左右,差別不太明顯;
針對(duì)GAPP產(chǎn)品提出想要定時(shí)持續(xù)更新司導(dǎo)位置的需求,最終采取了第二種方案.
2.計(jì)算經(jīng)緯度之間的距離
計(jì)算經(jīng)緯度之間的距離所需步驟:
- 獲取當(dāng)前位置信息
- 獲取另一個(gè)位置的經(jīng)緯度
- 計(jì)算兩個(gè)位置的距離
3.地理編碼&反地理編碼
地理編碼:輸入地理名稱,地理編碼獲得該位置的經(jīng)緯度.
反地理編碼:輸入經(jīng)緯度,輸出對(duì)應(yīng)位置的地理名稱
地理編碼步驟
- 創(chuàng)建 CLGeocoder對(duì)象
- 對(duì)地理名稱進(jìn)行地理編碼
- 對(duì)閉包中的CLPlacemark數(shù)據(jù)就行解析(遍歷)
一個(gè)地理名稱可能對(duì)應(yīng)多個(gè)地方,所以編碼后的到的結(jié)果是一個(gè)數(shù)組 - 獲取數(shù)組中元素的地理位置(經(jīng)緯度)
- 將經(jīng)緯度顯示到界面
反地理編碼步驟
- 拿到用戶輸入的經(jīng)緯度
- 對(duì)經(jīng)緯度進(jìn)行反地理編碼
- 對(duì)閉包中的CLPlacemark數(shù)據(jù)就行解析(遍歷)
一個(gè)經(jīng)緯度可能對(duì)應(yīng)多個(gè)位置(蘋(píng)果這么設(shè)計(jì)的) 所以編碼后返回一個(gè)數(shù)組
一個(gè)位置包含多個(gè)信息(省/市/街道/國(guó)家/經(jīng)緯度/) 編碼后的結(jié)果是字典數(shù)組 - 取出數(shù)組中的一個(gè)位置(字典),再獲取位置信息(取出字典的元素)
- 把獲取到的地理名稱顯示到界面
關(guān)于地理編碼和反地理編碼的實(shí)例,放到區(qū)域監(jiān)聽(tīng)的demo里做一并說(shuō)明.
4.區(qū)域監(jiān)聽(tīng) region
當(dāng)用戶進(jìn)入或者離開(kāi)某個(gè)區(qū)域的時(shí)候,對(duì)應(yīng)進(jìn)行某些操作
實(shí)例:打卡
筆者仿照釘釘寫(xiě)的打卡的小demo,大概功能如下:
1.當(dāng)不在考勤范圍內(nèi)時(shí),打卡顯示外勤打卡,顏色區(qū)分顯示,并提示當(dāng)前打卡位置
2.當(dāng)位置更換,進(jìn)入考勤范圍時(shí),顏色改變,打卡顯示正常打卡,并提示當(dāng)前打卡位置
4.1區(qū)域監(jiān)聽(tīng)步驟:
- 確定區(qū)域中心坐標(biāo)點(diǎn)
- 確定區(qū)域半徑
- 區(qū)域監(jiān)聽(tīng)方法,離開(kāi)某個(gè)區(qū)域和進(jìn)入某個(gè)區(qū)域時(shí)做相應(yīng)處理
4.2注意點(diǎn)
- 當(dāng)之前添加過(guò)監(jiān)聽(tīng)區(qū)域時(shí),再次添加新的監(jiān)聽(tīng)區(qū)域,還會(huì)對(duì)之前的區(qū)域進(jìn)行監(jiān)聽(tīng)
- 不想監(jiān)聽(tīng)之前的區(qū)域,必須通過(guò)代碼移除之前的區(qū)域
- 使用前先判斷區(qū)域監(jiān)聽(tīng)是否可用
- 注意監(jiān)聽(tīng)區(qū)域的個(gè)數(shù) (區(qū)域監(jiān)聽(tīng)個(gè)數(shù)有上限)
- 注意區(qū)域半徑是否大于最大監(jiān)聽(tīng)半徑