在使用Core Location以前,咱們必須將CoreLocation.framework
連接到Xcode項目中。在須要使用Core Location的源文件的中,導入框架#import <CoreLocation/CoreLocation.h>
。 html
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可能會使用這樣的定位服務設置。
框架
在某些狀況下,定位服務可能不可用。好比:ide
用戶在系統設置中禁用了定位服務。post
用於拒絕了某個App使用定位服務。ui
所以,在嘗試啓用定位服務以前,應該調用CLLocationManager
的類方法locationServicesEnable
。這個方法用來判斷系統的定位服務是否開發。若是返回NO
,當你嘗試開啓定位服務時,系統會提示用戶是否從新啓用定位服務。spa
standard location service是獲取用戶當前位置最經常使用的方式,由於全部的iOS和OS設備均可以使用。在使用以前,你須要對相關參數進行設置。好比指定位置數據的精度和從新獲取位置信息的移動距離。當啓動服務時,它會根據設置的參數決定硬件的工做方式,而後把定位相關的事件提交給你的App。標準定位服務很是適合那些位置信息精度要求很高的App(好比說導航類的App),由於它可讓定位跟蹤硬件長時間工做,隨之而來的就是電量的高消耗。
要使用標準定位服務,須要建立一個CLLocationManager
類的實例,而後設置它的desiredAccuracy
和distanceFilter
屬性。爲了可以接受到定位事件的通知,還要給這個實例的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時,一樣須要建立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
方法,能夠自定義輸出格式。
這兩項是須要添加到info.plist中的。若是info.plist中沒有這兩項存在,即便調用requestAlwaysAuthorization
和requestWhenInUseAuthorization
方法請求啓動定位服務,系統也會忽略請求。調用requestAlwaysAuthorization
須要info.plist中有NSLocationAlwaysUsageDescription
,調用requestWhenInUseAuthorization
須要info.plist中有NSLocationWhenInUseUsageDescription
。
這兩項只有在iOS 8.0以後的設備上會起做用,在iOS 6.0到iOS 8.0的設備上,使用NSLocationUsageDescription
來請求啓用定位服務。
通常定位系統所返回的位置信息都是經緯度
,將經緯度
逆向解析就能夠獲得咱們的須要的地址。
在Core Location框架下,使用CLGeocoder
和CLPlacemark
就能夠將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