iOS 系統(tǒng)自帶定位服務(wù)

iOS 自帶定位服務(wù)(原創(chuàng))

ps:本文粘貼自別處,只為學(xué)習(xí)記錄~

定位服務(wù)

iOS 7 提供了4種不同的途徑進(jìn)行定位,具體如下所示。

Wi-Fi。通過 Wi-Fi 路由器的地理位置信息查詢,比較省電。iPhone、iPod touch 和 iPad 都可以采用這種方式定位。

蜂窩式移動電話基站。通過移動運用商基站定位。只有 iPhone、3G 版本的 iPod touch和iPad可以采用這種方式定位。

GPS 衛(wèi)星。通過 GPS 衛(wèi)星位置定位,這種方式最為準(zhǔn)確,但是耗電量大,不能遮擋。iPhone、iPod touch 和 iPad 都可以采用這種方式定位。

iBeacon 微定位。iOS 7支持iBeacon技術(shù),iBeacon 技術(shù)是蘋果公司研發(fā)的,它使用低功耗藍(lán)牙技術(shù),通過多個 iBeacon 基站可以創(chuàng)建一個信號區(qū)域(地理圍欄),當(dāng)設(shè)備進(jìn)入該區(qū)域時,相應(yīng)的應(yīng)用程序便會提示用戶進(jìn)入了這個地理圍欄。

在對定位服務(wù)編程時,iOS 不像 Android 系統(tǒng)可以指定采用哪種途徑進(jìn)行定位。iOS 的 API 把底層這些細(xì)節(jié)屏蔽掉了,開發(fā)人員和用戶并不知道現(xiàn)在設(shè)備是采用哪種方式進(jìn)行定位的(微定位除外),iOS 系統(tǒng)會根據(jù)設(shè)備的情況 和周圍的環(huán)境采用一套最佳的解決方案。

也就是說,如果能夠接收 GPS 信息,那么設(shè)備優(yōu)先采用 GPS 定位,否則采用Wi-Fi 或蜂窩基站定位。在 Wi-Fi 和蜂窩基站之間,優(yōu)先使用 Wi-Fi,如果無法連接 Wi-Fi 才使用蜂窩基站定位。

定位服務(wù)編程

在 iOS 7 中,定位服務(wù)有比較大的變化,主要使用Core Location框架,定位時主要使用 CLLocationManager、 CLLocationManagerDelegate 和 CLLocation 這3個類,下面簡要介紹一下它們。

CLLocationManager。用于定位服務(wù)管理類,它能夠給我們提供位置信息和高度信息,也可以監(jiān)控設(shè)備 進(jìn)入或離開某個區(qū)域,還可以獲得設(shè)備的運行方向等。

CLLocationManagerDelegate。它是 CLLocationManager 類的委托協(xié)議。

CLLocation。該類封裝了位置和高度信息。

在定位服務(wù)的應(yīng)用中,第一次請求位置信息時,系統(tǒng)會提示用戶是否允許開啟定位服務(wù)。如圖所示,用戶所在的位置是比較私 密的信息,應(yīng)用獲取這些信息時,用戶是有知情權(quán)和否定權(quán)的。如果應(yīng)用在用戶不知情的情況下獲得其位置信息,這在某些國家是違法的。

如果用戶“不允許”,定位服務(wù)就無法獲得位置信息了。如果想改變這些設(shè)置,可以在系統(tǒng)“設(shè)置”應(yīng)用中 開啟或關(guān)閉,如圖所示。

如圖所示,我們可以關(guān)閉所有的定位服務(wù),此時只需關(guān)閉最上面的“定位服務(wù)”開關(guān)控件就可以了。 當(dāng)然,也可以關(guān)閉或開啟下面的具體應(yīng)用。

在應(yīng)用啟動進(jìn)入界面時,會獲得位置信息,并顯示在對應(yīng)的文本框中。如果設(shè)備位置發(fā)生變化,也會重新獲取位置信息,并更新對應(yīng)的文本框。

首先,為工程引入Core Location框架,具體步驟是選擇工程中的TARGETS→WhereAmI→Build Phases→Link Binary With Libraries,選擇右下角的+按鈕,打開“選擇要添加的框架和庫”對話框,如圖所示。

ViewController.h 中的代碼如下:

在上述代碼中,我們首先引入了CoreLocation/CoreLocation.h和CoreLocation/CLLocationManagerDelegate.h這兩個頭文件,然后在定義ViewController時聲明了CLLocationManagerDelegate協(xié)議。此外,我們還定義了CLLocationManager *locationManager屬性。 在 ViewController.m 中,viewDidLoad 方法的代碼如下:

- (void)viewDidLoad

{

[super viewDidLoad];

//初始化定位服務(wù)管理對象

_locationManager = [[CLLocationManager alloc] init];

_locationManager.delegate = self;

_locationManager.desiredAccuracy = kCLLocationAccuracyBest; (1)

_locationManager.distanceFilter = 1000.0f; (2)

}

在上述代碼中,我們主要對CLLocationManager的成員變量_locationManager進(jìn)行了初始化。首先,使用[[CLLocationManager alloc] init]語句實例化CLLocationManager對象,然后使用_locationManager. delegate = self語句設(shè)置定位服務(wù)委托為 self。

第(1)行代碼設(shè)置desiredAccuracy屬性,它是一個非常重要 的屬性,其取值有6個常量,具體如下所示。

kCLLocationAccuracyNearestTenMeters。精確到10米。

kCLLocationAccuracyHundredMeters。精確到100米。

kCLLocationAccuracyKilometer。精確到1000米。

kCLLocationAccuracyThreeKilometers。精確到3000米。

kCLLocationAccuracyBest。設(shè)備使用電池供電時最高的精度。

kCLLocationAccuracyBestForNavigation。導(dǎo)航情況下最高的精度,一般有外接電源時才能使用。

精度越高,請求獲得位置信息的時間就越短,這就意味著設(shè)備越耗電,因此一個應(yīng)用應(yīng)該選擇適合它的精度。 如果你的應(yīng)用是一個車載導(dǎo)航應(yīng)用,kCLLocationAccuracyBestForNavigation是比較好的選擇,你可以使用汽車上的電瓶為設(shè)備供電。 如果你的應(yīng)用是為徒步旅行者提供的導(dǎo)航應(yīng)用,kCLLocationAccuracyHundredMeters是一個不錯的選擇。

第(2)行代碼設(shè)置distanceFilter屬性,它是距離過濾器,定義了設(shè)備移動后獲得位置信息的最小距離,單位是米,本例設(shè)置為1000米。 初始化 CLLocationManager 類后,需要使用startUpdatingLocation方法開始定位服務(wù),該方法定義在ViewController.m的viewWillAppear:方法中。viewWillAppear:方法的代碼如下:

- (void)viewWillAppear:(BOOL)animated

{

[super viewWillAppear:animated]; //開始定位

[_locationManager startUpdatingLocation];

}

調(diào)用startUpdatingLocation方法時,就會開啟定位服務(wù)。根據(jù)設(shè)定的條件,它不斷請求回調(diào)新的位置信息。因此,開啟這個方法一定要慎重,在視圖控制器的聲明周期方法viewWillAppear:中使用這個方法是最合適的。與開啟服務(wù)對應(yīng)的方法是stopUpdatingLocation方法,它是在視圖控制器的viewWillDisappear:方 法中調(diào)用的。viewWillDisappear:方法的代碼如下:

- (void)viewWillDisappear:(BOOL)animated

{

[super viewWillDisappear:animated]; //停止定位

[_locationManager stopUpdatingLocation];

}

這個方法在視圖消失(應(yīng)用退到后臺)時調(diào)用,能夠保證最及時地關(guān)閉定位服務(wù)。在iOS 6中,請求有所變化, 定位服務(wù)應(yīng)用退入臺后,可以延遲更新位置信息,這可以通過allowDeferredLocationUpdatesUntil- Traveled:timeout:方法實現(xiàn)。要關(guān)閉延遲更新,可以使用disallowDeferredLocationUpdates方法實現(xiàn)。 此外,在iOS 6中,新增了pausesLocationUpdatesAutomatically屬性,它能設(shè)定自動暫停位置更新,而把 定位服務(wù)的開啟和暫停管理權(quán)交給系統(tǒng),這樣會更加合理和簡單。

一旦定位服務(wù)開啟,并設(shè)置好CLLocationManager委托屬性 delegate 后,當(dāng)用戶設(shè)備移動到達(dá)過濾距離時, 就會回調(diào)委托方法。與定位服務(wù)有關(guān)的方法有如下兩個。

locationManager:didUpdateLocations:。定位成功。這是iOS 6中新增的方法,替代了之前的locationManager:didUpdateToLocation:fromLocation:方法。

locationManager:didFailWithError:。定位失敗。

實現(xiàn) CLLocationManager 委托的代碼如下:

#pragma mark Core Location委托方法用于實現(xiàn)位置的更新

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:

(NSArray *)locations

{

CLLocation * currLocation = [locations lastObject]; (1)

_txtLat.text = [NSString stringWithFormat:@"%3.5f",currLocation.coordinate.latitude]; (2)

_txtLng.text = [NSString stringWithFormat:@"%3.5f",currLocation.coordinate.longitude]; (3)

_txtAlt.text = [NSString stringWithFormat:@"%3.5f",currLocation.altitude]; (4)

}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error

{

NSLog(@"error: %@",error);

}

在locationManager:didUpdateLocations:方法中,參數(shù)locations是位置變化的集合,它按照時間變化的順序存放。如果想獲得當(dāng)前設(shè)備的位置,可以使用 第(1)行中的[locations lastObject]語句獲得集合中的最后一個元素,它就是設(shè)備的當(dāng)前位置了。從集合中返回的對象類型是 CLLocation,CLLocation 封裝了位置、高度等信息。在上面的代碼中,我們使用了它的兩個屬性altitude和coordinate,其中前者是高度值,后者是封裝經(jīng)度和緯度的結(jié)構(gòu)體CLLocationCoordinate2D。CLLocationCoordinate2D的定義如下:

typedef struct {

CLLocationDegrees latitude; //緯度 CLLocationDegrees longitude; //經(jīng)度

} CLLocationCoordinate2D;

其中l(wèi)atitude為緯度信息,longitude為經(jīng)度信息,它們都是CLLocationDegrees類型。CLLocationDegrees是使用typedef定義的double類型。

第(2)行代碼中的currLocation.coordinate.latitude表達(dá)式用于獲得設(shè)備當(dāng)前的緯度,

第(3)行代碼中的currLocation.coordinate.longitude表達(dá)式用于獲得設(shè)備當(dāng)前的經(jīng)度,

第(4)行代碼中的currLocation. altitude表達(dá)式用于獲得高度。

關(guān)于定位服務(wù)的測試

一般情況下,定位服務(wù)應(yīng)用的測試和運行有兩個選擇:模擬器和設(shè)備。原則上,我們先通過模擬器,然后再 使用設(shè)備測試。由于定位服務(wù)的特點,使用設(shè)備測試時我們需要到現(xiàn)場進(jìn)行測試,所以有的時候有一定的局限性。 因此,使用模擬器測試有的時候是不可替代的。

在 Xcode 早期版本中,模擬器是不能模擬位置信息的變化的,請求獲取位置信息只是固定蘋果公司總部地址。 而現(xiàn)在的 Xcode 版本預(yù)先設(shè)置了幾個地址,我們可以模擬改變位置。如果想讓模擬器一開始運行的時候就能夠獲 得模擬數(shù)據(jù),可以在啟動參數(shù)中設(shè)置。首先,在 Xcode 工具的左上角編輯應(yīng)用的Scheme,如圖所示。

選擇Edit Scheme菜單后,彈出如圖所示的對話框,從中選擇Run WhereAmI.app→Options,在Core Location項目中選中Allow Location Simulation復(fù)選框,然后在下面的Default Location下拉框中選擇你感興趣的城市。

這樣應(yīng)用啟動時,就會模擬定位到你選擇的城市了。如果列表中沒有我們需要的地點,可以使用最下面的Add GPX File to Project菜單項為工程添加一個GPX1文件。下面是 GPX 文件的內(nèi)容:


creator="MyGeoPosition.com" version="1.1"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.topografix.com/GPX/1/1

http://www.topografix.com/GPX/1/1/gpx.xsd">

中國北京 東城區(qū)北京站東街北京 郵政編碼: 100005 MyGeoPosition.com http://mygeoposition.com

標(biāo)簽中的lat屬性設(shè)置緯度,lon屬性設(shè)置經(jīng)度。自己手寫這個文件還是比較麻煩的,一般使用http://www.mygeoposition.com網(wǎng)站提供的GPX工具工具生成。這個網(wǎng)站免費提供地理信息編碼和反編碼、生成 KML 和 GPX 文件等服務(wù)。

GPX(GPS eXchange Format,GPS交換格式)是一個 XML 格式,是為應(yīng)用軟件設(shè)計的通用 GPS 數(shù)據(jù)格式。

得到 GPX 文件后,可以通過如圖所示的Add GPX File to Project菜單項將它添加到 Xcode 工程中,此時在菜單中就會出現(xiàn)GPX文件了。如果我添加的文件名是test.gpx,則在菜單中出現(xiàn) test 菜單項,選擇 test 即可使用這個模擬坐標(biāo)數(shù)據(jù)了。

如果在應(yīng)用啟動參數(shù)中沒有設(shè)置初始的模擬位置數(shù)據(jù),我們還可以在運行之后設(shè)置。在調(diào)試工具欄中選擇模 擬定位按鈕,即可選擇模擬位置,如圖所示。

Xcode 中的模擬器還提供了連續(xù)位置變化測試能力。如果想開發(fā)導(dǎo)航應(yīng)用,這個功能對我們有很大的幫助。 此外,模擬器有幾個固定的模式,可以發(fā)出連續(xù)變化的位置數(shù)據(jù)。打開模擬菜單的“調(diào)試”→“位置”,可以發(fā) 現(xiàn)共有7個菜單項,

其中后面3個都能發(fā)出連續(xù)的位置變化數(shù)據(jù),它們的起始點從蘋果公司總部開始,按照一個固定的線路運動,這三者的區(qū)別是City Bicycle Ride是最慢的,City Run要快一些,Freeway Drive最快。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容