使用Core Location獲取用戶的位置

在使用Core Location以前,咱們必須將CoreLocation.framework連接到Xcode項目中。在須要使用Core Location的源文件的中,導入框架#import <CoreLocation/CoreLocation.h>html

image

獲取用戶當前位置

Core Location可以讓咱們定位當前的位置,並在App中使用位置信息。它會記錄設備位置,而且能夠進行週期性更新。它的所做所爲,均取決於咱們對定位服務的設置。 ios

有兩種服務能夠獲取當前位置:git

  • standard location service。 它是可配置,能夠知足基本需求的解決方案。能夠獲取位置信息,根據精度設置跟蹤位置變化。數組

  • significant-change location service。 只有當設備的位置有大的改變時,好比移動500米或者更遠,纔會提交更新請求。app

收集位置信息是一個很是耗電的操做。不管位置信息在你的App裏是多麼重要,咱們都應該合理地設置它、使用它,避免設備的點亮被大量消耗。若是,你的App即便在後臺也須要對位置進行管理的話,在info.plist中,添加UIBackgroundModes字段(它是一個數組類型),加入location值。這時,將location manager的pausesLocationUpdatesAutomatically屬性設爲YES,以節省電量。好比,與健康、路線規劃導航相關的App可能會使用這樣的定位服務設置。
image框架

判判定位服務是否可用

在某些狀況下,定位服務可能不可用。好比:ide

  • 用戶在系統設置中禁用了定位服務。post

  • 用於拒絕了某個App使用定位服務。ui

所以,在嘗試啓用定位服務以前,應該調用CLLocationManager的類方法locationServicesEnable。這個方法用來判斷系統的定位服務是否開發。若是返回NO,當你嘗試開啓定位服務時,系統會提示用戶是否從新啓用定位服務。spa

啓用Standard Location Service

standard location service是獲取用戶當前位置最經常使用的方式,由於全部的iOS和OS設備均可以使用。在使用以前,你須要對相關參數進行設置。好比指定位置數據的精度和從新獲取位置信息的移動距離。當啓動服務時,它會根據設置的參數決定硬件的工做方式,而後把定位相關的事件提交給你的App。標準定位服務很是適合那些位置信息精度要求很高的App(好比說導航類的App),由於它可讓定位跟蹤硬件長時間工做,隨之而來的就是電量的高消耗。

要使用標準定位服務,須要建立一個CLLocationManager類的實例,而後設置它的desiredAccuracydistanceFilter屬性。爲了可以接受到定位事件的通知,還要給這個實例的delegate賦值。最後,調用startUpdatingLocation方法。一旦獲取到位置信息,location manager就會通知它的delegate。若是最新的位置信息被提交到App,你能夠直接從CLLocationManager對象獲取到最近一次的位置信息。調用location manager對象的stopUpdatingLocation方法能夠中止提交位置信息。

接下來,給出一段代碼,按照上面的步驟啓用標準定位服務。

- (void)startStandardUpdates {
    //若是locactionManager未初始化,則進行初始化
    if (self.locationManager == nil) {
        self.locationManager = [[CLLocationManager alloc] init];
    }
    self.locationManager.delegate = self;
    //設置`精度`和`觸發更新事件的最短水平距離`
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    self.locationManager.distanceFilter = 5;
    //開啓標準定位服務
    [self.locationManager startUpdatingLocation];
}

distanceFilter屬性在更新位置以前設備須要移動的最短水平距離,單位是米。上述代碼值爲5,表示至少移動5米纔會更新一次位置信息。它的默認值是kCLDistanceFilterNone,表示移動任何距離都會更新一次位置信息,即便不移動依然會更新位置信息。

啓用Significant-Change Location Service

啓用significant-change location service時,一樣須要建立CLLocationManager類的對象,而後給它的delegate賦值,調用startMonitoringSignificantLocationChanges方法就能夠了。

注意:使用這個服務時,CLAuthorizationStatus的值要設爲kCLAuthorizationStatusAuthorizedAlways,使App能夠在任什麼時候間使用定位服務。

- (void)startSignificantChangeUpdates
{
    if (self.locationManager == nil)
        self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;
    [self.locationManager startMonitoringSignificantLocationChanges];
}

接收位置信息

不管使用哪種定位服務,接收位置數據的方法都是同樣的。當位置數據可取時,location manager會調用locationManager:didUpdateLocations:代理方法。在接收數據出錯時,location manager會調用locationManager:didFailWithError:代理方法。

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
    CLLocation* location = [locations lastObject];
    NSDate* eventDate = location.timestamp;
    NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
    //根據取到的location的時間戳,輸出經緯度
    if (fabs(howRecent) < 15.0) {
        NSLog(@"latitude %+.6f, longitude %+.6f\n",
              location.coordinate.latitude,
              location.coordinate.longitude);
    }
}

CLLocation對象除了時間戳以外,還包括

  • 座標_coordinate_。有經度和緯度。

  • 海拔_atitude_。正數表示在海平面以後,負數表示在海平面之下。

  • 樓層數_floor_。若是沒法獲取,則被置爲nil。

  • 水平精度_horizontalAccuracy_。單位是米。以經緯度爲中心的圓的半徑。若是爲負數,說明經緯度無效。

  • 垂直精度_verticalAccuracy_。單位是米。表示海拔上的偏差。若是爲負數,說明經緯度無效。這個屬性須要iOS設備有GPS功能。所以,在老一批的iOS設備上,這個值永遠會返回負數。

  • _description_。它是一個格式化的字符串,包含CLLocation對象能夠包含的全部屬性的值。使用NSLog輸出CLLoctation對象時,就是輸出這個屬性的值。和一些類的description方法是同樣的東西。重寫CLLocation的(NSString*)description方法,能夠自定義輸出格式。

NSLocationAlwaysUsageDescription和NSLocationWhenInUseUsageDescription

這兩項是須要添加到info.plist中的。若是info.plist中沒有這兩項存在,即便調用requestAlwaysAuthorizationrequestWhenInUseAuthorization方法請求啓動定位服務,系統也會忽略請求。調用requestAlwaysAuthorization須要info.plist中有NSLocationAlwaysUsageDescription,調用requestWhenInUseAuthorization須要info.plist中有NSLocationWhenInUseUsageDescription

這兩項只有在iOS 8.0以後的設備上會起做用,在iOS 6.0到iOS 8.0的設備上,使用NSLocationUsageDescription來請求啓用定位服務。

image

經緯度逆向解析

通常定位系統所返回的位置信息都是經緯度,將經緯度逆向解析就能夠獲得咱們的須要的地址。

在Core Location框架下,使用CLGeocoderCLPlacemark就能夠將CLLocation中的信息解析成地址。

拿上面的代理方法中獲得的CLLocation實例作解析對象。

CLGeocoder* geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
    NSLog(@"%@",[placemarks lastObject].name);
}];

先看一下輸出的結果。

2016-03-08 15:58:03.076 latitude +30.283291, longitude +120.115639
2016-03-08 15:58:09.841 西湖國際科技大廈D座

CLPlacemark還有許多與該地址相關的屬性,能夠輸出看一下。

2016-03-08 16:04:09.645 name:西湖國際科技大廈D座
2016-03-08 16:04:09.646 ISOcountryCode:CN
2016-03-08 16:04:09.646 country:中國
2016-03-08 16:04:09.647 postalCode:(null)
2016-03-08 16:04:09.647 administrativeArea:浙江省
2016-03-08 16:04:09.647 subAdministrativeArea:(null)
2016-03-08 16:04:09.647 locality:杭州市
2016-03-08 16:04:09.647 subLocality:西湖區
2016-03-08 16:04:09.647 thoroughfare:文二路391西湖國際科技大廈
2016-03-08 16:04:09.648 subThoroughfare:(null)
2016-03-08 16:04:09.648 region:CLCircularRegion (identifier:'<+30.28099700,+120.12021500> radius 197.16', center:<+30.28099700,+120.12021500>, radius:197.16m)
2016-03-08 16:04:09.649 timeZone:Asia/Shanghai (GMT+8) offset 28800

在結果中咱們能夠看出:

  • name:地址名稱

  • ISOcountryCode:國家代碼

  • country:國家

  • administrativeArea:省份

  • locality:所屬城市

  • subLocality:所屬城市中的區、縣等

  • thoroughfare:帶街道的地址名稱

  • timeZone:時區

參考文檔

Core Location Framework Reference
Getting the User’s Location

相關文章
相關標籤/搜索