你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS學習筆記19-地圖(一)定位CoreLocation

iOS學習筆記19-地圖(一)定位CoreLocation

編輯:IOS開發綜合

一、定位介紹

現在很多社交、電商、團購應用都引入了地圖和定位功能,似乎地圖功能不再是地圖應用和導航應用所特有的。的確,有了地圖和定位功能確實讓我們的生活更加豐富多彩,極大的改變了我們的生活方式。要實現地圖、導航功能,往往需要先熟悉定位功能

在iOS中通過CoreLocation框架進行定位操作。

CoreLocation自身可以單獨使用,和地圖開發框架MapKit完全是獨立的,但是往往地圖開發要配合定位框架使用。

CoreLocation可以實現的功能:
定位功能 地理編碼與逆地理編碼

\

二、定位核心類

定位是一個很常用的功能,如一些地圖軟件打開之後如果用戶允許軟件定位的話,那麼打開軟件後就會自動鎖定到當前位置,如果用戶手機移動那麼當前位置也會跟隨著變化。要實現這個功能需要使用CoreLoactionCLLocationManager類,下面是這個類的使用說明:

1. 類方法:
+ (BOOL)locationServicesEnabled;/* 返回用戶是否啟用定位服務 */
+ (CLAuthorizationStatus)authorizationStatus;/* 定位服務授權狀態,返回枚舉類型 */

typedefNS_ENUM(int,CLAuthorizationStatus){
    kCLAuthorizationStatusNotDetermined = 0, /* 用戶尚未決定是否啟用定位服務 */
    kCLAuthorizationStatusRestricted, /* 沒有獲得用戶授權 */
    kCLAuthorizationStatusDenied, /* 用戶禁止使用定位或者定位服務處於關閉狀態 */
    kCLAuthorizationStatusAuthorizedAlways, /*前台、後台定位授權 */
    kCLAuthorizationStatusAuthorizedWhenInUse, /* 前台定位授權 */
};
2. 對象屬性:
定位精度desiredAccuracy
枚舉類型:
\ 位置信息更新最小距離distanceFilter
浮點數,默認為kCLDistanceFilterNone,表示不進行距離限制
3. 對象方法:
#pragma mark - 定位追蹤
-(void)startUpdatingLocation;/* 開始定位追蹤 */
-(void)stopUpdatingLocation;/* 停止定位追蹤 */
#pragma mark - 導航追蹤
-(void)startUpdatingHeading;/* 開始導航方向追蹤 */
-(void)stopUpdatingHeading;/* 停止導航方向追蹤 */
#pragma mark - 區域定位追蹤
-(void)startMonitoringForRegion:(CLRegion *)region;/* 開始對某個區域進行定位追蹤 */
-(void)stopMonitoringForRegion:(CLRegion *)region;/* 停止對某個區域進行定位追蹤 */
#pragma mark - 授權請求
-(void)requestWhenInUseAuthorization;/* 請求獲得應用前台定位授權 */
-(void)requestAlwaysAuthorization;/* 請求獲得應用前後台定位授權 */
4. 常用代理方法CLLocationManagerDelegate
/* 位置發生改變後調用,第一次定位也會調用 */
-(void)locationManager:(CLLocationManager *)manager 
    didUpdateLocations:(NSArray *)locations;
/* 導航方向發生變化後調用 */
-(void)locationManager:(CLLocationManager *)manager 
      didUpdateHeading:(CLHeading *)newHeading;
/* 進入某個區域後調用 */
-(void)locationManager:(CLLocationManager *)manager 
        didEnterRegion:(CLRegion *)region;
/* 走出某個區域後調用 */
-(void)locationManager:(CLLocationManager *)manager 
         didExitRegion:(CLRegion *)region;
/* 當用戶授權狀態發生變化時調用 */
-(void)locationManager:(CLLocationManager *)manager 
       didChangeAuthorizationStatus:(CLAuthorizationStatus)status;

三、定位簡單使用

先要在項目導入CoreLocation框架,然後再導入頭文件:
#import 
iOS版本不同,使用也有一些區別,主要區分為:
iOS8.0之前的定位使用 iOS8.0之後的定位使用
1. iOS8.0之前的定位使用:
1.1 前台定位:
- (void)viewDidLoad{
    [super viewDidLoad];
    if (![CLLocationManager locationServicesEnabled]) {
        NSLog(@"定位服務當前可能尚未打開,請設置打開!");
        return;
    }
    [self initLocationManager];
    //調用方法,開始更新用戶位置信息
    [self.locationM startUpdatingLocation];
}
//創建CLLocationManager並啟動定位
- (void)initLocationManager{
    //創建CLLocationManager對象並設置代理
    self.locationM = [[CLLocationManager alloc] init];
    self.locationM.delegate = self;
    //設置定位精度和位置更新最小距離
    self.locationM.distanceFilter = 100;
    self.locationM.desiredAccuracy = kCLLocationAccuracyBest;
}
//在對應的代理方法中獲取位置信息
- (void)locationManager:(CLLocationManager *)manager 
     didUpdateLocations:(NSArray *)locations
{
    CLLocation *location = [locations firstObject];//取出第一個位置
    /* 
        使用位置前, 務必判斷當前獲取的位置是否有效
        如果水平精確度小於零, 代表雖然可以獲取位置對象, 但是數據錯誤, 不可用
     */
    if (location.horizontalAccuracy < 0)
        return;
    CLLocationCoordinate2D coordinate = location.coordinate;//位置坐標 
    CGFloat longitude = coordinate.longitude;//經度
    CGFloat latitude = coordinate.latitude;//緯度
    CGFloat altitude = location.altitude;//海拔
    CGFloat course = location.course;//方向
    CGFloat speed = location.speed;//速度
    NSLog(@"經度:%f,緯度:%f",longitude,latitude);   
    NSLog(@"海拔:%f,方向:%f,速度:%f",altitude,course,speed);
    //如果不需要實時定位,使用完即使關閉定位服務
    [self.locationM stopUpdatingLocation];   
}
定位頻率和定位精度並不是越精確越好,需要視實際情況而定,因為越精確越耗性能,也就越費電。 定位成功後會根據設置情況頻繁調用locationManager:didUpdateLocations:方法 每個元素一個CLLocation代表地理位置信息,之所以返回數組是因為有些時候一個位置點可能包含多個位置。 使用完定位服務後,如果不需要實時監控應該立即關閉定位服務,以節省資源。 除了提供定位功能,還可以調用startMonitoringForRegion:方法對指定區域進行監控。
1.2 後台定位:

在前台的基礎上,勾選後台模式Location updates
\

2. iOS8之後的定位使用
iOS8開始,需要請求定位授權:
前台授權:
在Info.plist文件中配置 NSLocationWhenInUseUsageDescriptionYES
\ 前後台授權:
在Info.plist文件中配置NSLocationAlwaysUsageDescriptionYES
\
- (void)viewDidLoad{
    [super viewDidLoad];
    if (![CLLocationManager locationServicesEnabled]) {
        NSLog(@"定位服務當前可能尚未打開,請設置打開!");
        return;
    }
    [self initLocationManager];
    //如果沒有授權,則請求用戶授權
    CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
    if (status == kCLAuthorizationStatusNotDetermined){
        //請求前台定位授權
        //[self.locationM requestWhenInUseAuthorization];
        //請求前後台定位授權
        [self.locationM requestAlwaysAuthorization];
    }
}

//創建CLLocationManager並啟動定位
- (void)initLocationManager{
    //創建CLLocationManager對象並設置代理
    self.locationM = [[CLLocationManager alloc] init];
    self.locationM.delegate = self;
    //設置定位精度和位置更新最小距離
    self.locationM.distanceFilter = 100;
    self.locationM.desiredAccuracy = kCLLocationAccuracyBest;
}
// 當用戶授權狀態發生變化時調用
- (void)locationManager:(CLLocationManager *)manager 
        didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    switch (status) {
        case kCLAuthorizationStatusNotDetermined://用戶還未決定
        {
            NSLog(@"用戶還未決定");
            break;
        }
        case kCLAuthorizationStatusRestricted://訪問受限
        {
            NSLog(@"訪問受限");
            break;
        }
        case kCLAuthorizationStatusDenied://定位關閉時或用戶APP授權為永不授權時調用
        {
            NSLog(@"定位關閉或者用戶未授權");
            break;
        }
        case kCLAuthorizationStatusAuthorizedAlways://獲取前後台定位授權
        {
            NSLog(@"獲取前後台定位授權");
            [self.locationM startUpdatingLocation];
            break;
        }
        case kCLAuthorizationStatusAuthorizedWhenInUse://獲得前台定位授權
        {
            NSLog(@"獲得前台定位授權");
            [self.locationM startUpdatingLocation];
            break;
        }
        default:break;
    }
}
//在對應的代理方法中獲取位置信息
- (void)locationManager:(CLLocationManager *)manager 
     didUpdateLocations:(NSArray *)locations
{
    CLLocation *location = [locations firstObject];//取出第一個位置
    /* 
        使用位置前, 務必判斷當前獲取的位置是否有效
        如果水平精確度小於零, 代表雖然可以獲取位置對象, 但是數據錯誤, 不可用
     */
    if (location.horizontalAccuracy < 0)
        return;
    CLLocationCoordinate2D coordinate = location.coordinate;//位置坐標
    CGFloat longitude = coordinate.longitude;//經度
    CGFloat latitude = coordinate.latitude;//緯度
    CGFloat altitude = location.altitude;//海拔
    CGFloat course = location.course;//方向
    CGFloat speed = location.speed;//速度
    NSLog(@"經度:%f,緯度:%f",longitude,latitude);
    NSLog(@"海拔:%f,方向:%f,速度:%f",altitude,course,speed);
    //如果不需要實時定位,使用完即使關閉定位服務
    [self.locationM stopUpdatingLocation];
}

控制台打印

四、地理編碼

定位服務中還包含CLGeocoder類,用於處理地理編碼和逆地理編碼功能。
* 地理編碼:根據給定的位置(通常是地名)確定地理坐標(經、緯度)。
【位置 -> 地理坐標】
* 逆地理編碼:可以根據地理坐標(經、緯度)確定位置信息(街道、門牌等)。
【地理坐標 -> 位置】

- (void)viewDidLoad {
    [super viewDidLoad];
    self.geocoder = [[CLGeocoder alloc] init];
    [self getCoordinateByAddress:@"北京"];
    [self getAddressByLatitude:39.54 longitude:116.28];
}

#pragma mark 根據地名確定地理坐標
-(void)getCoordinateByAddress:(NSString *)address{
    //地理編碼
    [self.geocoder geocodeAddressString:address 
                      completionHandler:^(NSArray *placemarks, NSError *error) {
        //取得第一個地標,地標中存儲了詳細的地址信息,注意:一個地名可能搜索出多個地址
        CLPlacemark *placemark = [placemarks firstObject];
        CLLocation *location = placemark.location;//位置
        CLRegion *region = placemark.region;//區域
        NSDictionary *addressDic = placemark.addressDictionary;//詳細地址信息字典
        NSLog(@"位置:%@,區域:%@,詳細信息:%@",location,region,addressDic);
    }];
}
#pragma mark 根據坐標取得地名
-(void)getAddressByLatitude:(CLLocationDegrees)latitude 
                  longitude:(CLLocationDegrees)longitude
{
    //反地理編碼
    CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude 
                                                      longitude:longitude];
    [self.geocoder reverseGeocodeLocation:location 
                        completionHandler:^(NSArray *placemarks, NSError *error) {
        CLPlacemark *placemark = [placemarks firstObject];
        NSLog(@"詳細信息:%@",placemark.addressDictionary);
    }];
}
地標類CLPlacemark還包含以下信息:
NSString *name = placemark.name;//地名
NSString *thoroughfare = placemark.thoroughfare;//街道
NSString *subThoroughfare = placemark.subThoroughfare; //街道相關信息,例如門牌等
NSString *locality = placemark.locality; // 城市
NSString *subLocality = placemark.subLocality; // 城市相關信息,例如標志性建築
NSString *administrativeArea = placemark.administrativeArea; // 州
NSString *subAdministrativeArea = placemark.subAdministrativeArea; //其他行政區域信息
NSString *postalCode = placemark.postalCode; //郵編
NSString *ISOcountryCode = placemark.ISOcountryCode; //國家編碼
NSString *country = placemark.country; //國家
NSString *inlandWater = placemark.inlandWater; //水源、湖泊
NSString *ocean = placemark.ocean; // 海洋
NSArray *areasOfInterest = placemark.areasOfInterest; //關聯的或利益相關的地標
下一節我會寫地圖類MapKit的相關筆記,敬請期待吧!有什麼問題可以在下方評論區提出,O(∩_∩)O哈!
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved