iOS開發-用戶定位獲取-CoreLocation的實際應用-CLLocationManger獲取定位權限-CLLocation詳細使用方式

iOS提供了兩個框架用來定位以及地圖顯示。CoreLocation框架包含的類可以幫助設備確定位置和航向以及使用基於位置的有效信息。MapKit框架未定位提供了戶用頁面的支持(地圖顯示),裏面包含了地圖視圖、衛星地圖視圖以及2D、3D混合視圖,並且能夠讓開發人員管理地圖標註和地圖覆蓋層,前者 用於標註地點(常見的地圖大頭針),後者用來突出某區域或者路線等。

本期內容:

  • CLLocationManager申請定位權限
  • CLLocationManager獲取用戶定位
  • CLLocation詳細使用,定位數據處理
  • GPX虛擬定位文件的使用以及模擬器定位使用

CLLocationManager 定位管理器

簡介:CLLocationManager是用於啓動和停止向App獲取位置相關的事件的對象。
只有在得到用戶許可的情況下,App才能獲取設備的當前位置,但是在獲取設備位置之前,App還必須確保設備啓動了定位服務,當滿足這些條件後,App就可以獲取啓動位置請求的權限並獲取當前位置。


CLLocationManager申請定位權限

那我們就開始了,首先要去項目的target裏設置info.plist文件字段(蘋果的隱私安全需求,不添加是不允許使用的),如下圖標註的三個字段:
在這裏插入圖片描述
接下來我們開始敲代碼,創建一個定位管理器CLLocationManager,但是剛剛我們也說過了,如果系統沒有打開定位服務,那麼我們獲得授權也是沒用的,所以,首先判斷設備是否打開了定位服務:

    // 1.檢查定位服務是否開啓
    if ([self checkLocationServiceIsEnabled]) {
        // 2.創建定位管理器:
        [self createCLManager];
    }

檢查的內部實現:

- (BOOL)checkLocationServiceIsEnabled{
	// 該方法是類方法,和我們創建的管理器沒有關係
    if ([CLLocationManager locationServicesEnabled]) {
        return YES;
    }
    UIAlertController * alertVC = [UIAlertController alertControllerWithTitle:@"提示" message:@"系統定位尚未打開,請到【設定-隱私】中手動打開" preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction * tipsAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleCancel handler:nil];
    [alertVC addAction:tipsAction];
    [self presentViewController:alertVC animated:YES completion:nil];
    return NO;
}

創建定位管理器內部實現:

- (void)createCLManager{
    // 創建CoreLocation管理對象
    self.locaationManager = [[CLLocationManager alloc]init];
    // 設定定位精準度
    [self.locaationManager setDesiredAccuracy:kCLLocationAccuracyBest];
    // 設定DistanceFilter可以在用戶移動指定距離之後觸發更新事件(100米更新一次)
    [self.locaationManager setDistanceFilter:100.f];
    // 設置代理
    self.locaationManager.delegate = self;
    // 開始更新定位
    [self.locaationManager startUpdatingLocation];
}

在這裏說一下定位的精準度,這是一個枚舉,具體的有以下方式:

精準度枚舉 作用
kCLLocationAccuracyBestForNavigation 最佳精確度(汽車導航使用)
kCLLocationAccuracyBest 最佳精確度
kCLLocationAccuracyNearestTenMeters 10米誤差
kCLLocationAccuracyHundredMeters 百米誤差
kCLLocationAccuracyKilometer 千米誤差
kCLLocationAccuracyThreeKilometers 三千米誤差

這會兒我們的定位管理器就創建好了,但是到了這一步還是沒法使用定位,因爲,用戶還沒有授權給我們的App獲取定位權限,所以這會兒我們就需要去主動給用戶通知,讓用戶授權,使用的是CLLocationManager的代理方法:

// 代理方法,定位權限檢查
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
    switch (status) {
        case kCLAuthorizationStatusNotDetermined:{
            NSLog(@"用戶還未決定授權");
            // 主動獲得授權
            [self.locaationManager requestWhenInUseAuthorization];
            break;
        }
        case kCLAuthorizationStatusRestricted:
        {
            NSLog(@"訪問受限");
            // 主動獲得授權
            [self.locaationManager requestWhenInUseAuthorization];
            break;
        }
        case kCLAuthorizationStatusDenied:{
            // 此時使用主動獲取方法也不能申請定位權限
            // 類方法,判斷是否開啓定位服務 
            if ([CLLocationManager locationServicesEnabled]) {
                NSLog(@"定位服務開啓,被拒絕");
            } else {
                NSLog(@"定位服務關閉,不可用");
            }
            break;
        }
        case kCLAuthorizationStatusAuthorizedAlways:{
            NSLog(@"獲得前後臺授權");
            break;
        }
        case kCLAuthorizationStatusAuthorizedWhenInUse:{
            NSLog(@"獲得前臺授權");
            break;
        }
        default:
            break;
    }
}

在上述方法中,我們使用[self.locaationManager requestWhenInUseAuthorization]去主動獲得授權,但也需要注意裏面的兩個場景是無法獲得授權的。

完成了以上步驟,我們就可以獲得權限了,然後我們開始去獲得定位


CLLocationManager獲取用戶定位

CLLocationManager在獲取定位的時候是通過代理方法實現的,該方法包裝了類型爲CLLocation的定位數據數組,並返回給代理中,具體實現如下:

// 代理方法,更新位置
-  (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
    // locations是一個數組提供了一連串的用戶定位,所以在這裏我們只取最後一個(當前最後的定位)
    CLLocation * newLocation = [locations lastObject];
    // 判空處理
    if (newLocation.horizontalAccuracy < 0) {
        UIAlertController * alertVC = [UIAlertController alertControllerWithTitle:@"提示" message:@"定位錯誤,請檢查手機網絡以及定位" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction * tipsAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleCancel handler:nil];
        [alertVC addAction:tipsAction];
        [self presentViewController:alertVC animated:YES completion:nil];
        return;
    }
    
    // 獲取定位經緯度
    CLLocationCoordinate2D coor2D = newLocation.coordinate;
    NSLog(@"緯度爲:%f, 經度爲:%f", coor2D.latitude, coor2D.longitude);
    
    // 獲取定位海拔高度
    CLLocationDistance altitude = newLocation.altitude;
    NSLog(@"高度爲:%f", altitude);
    
    // 獲取定位水平精確度, 垂直精確度
    CLLocationAccuracy horizontalAcc = newLocation.horizontalAccuracy;
    CLLocationAccuracy verticalAcc = newLocation.verticalAccuracy;
    NSLog(@"%f, %f", horizontalAcc, verticalAcc);
    
    // 停止更新位置
    [self.locaationManager stopUpdatingLocation];
}

運行效果如下:
在這裏插入圖片描述
這樣我們的位置信息就獲取完成了,可能大家看到了,在這個位置信息獲取完成之後爲什麼要寫上一個停止更新位置呢?在此我就來解答依稀,一般來說蘋果建議我們在獲取完位置之後就停止定位,因爲電量的消耗是非常大的,但如果我們需要,可以使用以下方法:
[self.locaationManager startMonitoringSignificantLocationChanges]
該方法可以說是一個重大變化通知,避免了隨時定位的耗電,當設備檢查到數據變化大,就主動調起didUpdateLocations方法來完成位置的改變。

CLLocation詳細使用,定位數據處理

在上面我們看到了一個類:CLLocation。和CLLocationManager很像是吧?官方有話說:CLLocation對象包含設備的地理位置和高度,以及指示這些測量值的準確性和收集時間的值。在iOS中,位置對象還包含航向信息,即設備移動的速度和方向。

那我們如何來獲得這些信息呢?上代碼:

- (void)learningCLLocation{
    /**
     定位管理器返回的位置是用CLLoation實例表示的,裏面包含了有關位置的重要信息
     比如:
     CLLocationCoordinate2D 用來表示經緯度座標
     使用方式:
     CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude) 創建一個經緯度座標
     coordinate.latitude,coordinate.longitude 讀取經緯度
     
     CLLocationDistance  用來表示實際位置和返回座標之間的距離(以米爲單位)
     使用方式:獲取
     location.altitude
     
     CLLocationAccuracy 地理座標的準確性
     使用方式:獲取
     location.horizontalAccuracy; 指定座標的水平精度(以米爲單位)
     location.verticalAccuracy; 高度值的精度(以米爲單位)
     
     timestamp 時間戳,指出何時在定位管理器獲取的位置
     使用方式:獲取
     location.timestamp
     
     CLLocationSpeed 裝置運動的速度(以米每秒爲單位)
     使用方式:獲取
     location.speed
     
     CLLocationDirection 方位角以相對於真北的角度來測量的方位角
     使用方式:獲取
     location.course
     */
}

已經很詳細的表達出來啦,這些數據可能會有用,希望大家能記下來。雖然我們已經獲取了定位的數據,但這些數據我們確實看着不懂,那我們該怎麼辦呢?蘋果提供了一個CLGeocoder類,這個類是用於在地理座標和地名之間轉換的接口,也就是常說的逆地理編碼(反地理編碼)

// 反地理編碼(根據當前的經緯度獲取具體的位置信息)
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) {
        for (CLPlacemark *placeMark in placemarks) {
            NSLog(@"位置:%@", placeMark.name);
            NSLog(@"街道:%@", placeMark.thoroughfare);
            NSLog(@"子街道:%@", placeMark.subThoroughfare);
            NSLog(@"市:%@", placeMark.locality);
            NSLog(@"區\\縣:%@", placeMark.subLocality);
            NSLog(@"行政區:%@", placeMark.administrativeArea);
            NSLog(@"國家:%@", placeMark.country);
        }
    }];

實現之後效果如下:
在這裏插入圖片描述
這樣我們的當前定位數據就是很直觀的展現出來啦。


GPX虛擬定位文件的使用以及模擬器定位使用

當我們沒有真機調試或者需要進行簡單的定位調試的時候,我們會使用GPX虛擬定位文件或者直接使用模擬器的定位工具,可能有的小夥伴不太懂,我這裏就給大家講一下:

  • GPX虛擬定位文件
    首先在工程中 cmd + n 打開文件創建頁面,找到gpx文件,如圖:在這裏插入圖片描述
    然後在選擇運行設備的地方選擇 Eidt Scheme,按照下圖方式進行操作:
    在這裏插入圖片描述
    然後就會在項目中發現我們的GPX虛擬定位文件啦,之後我們在該文件裏面作出修改,運行項目,就可以獲得目標位置的信息,修改文件內容如下圖:
    在這裏插入圖片描述
    把lat和lng以及name修改就行,時間戳不用修改,這樣我們的GPX虛擬定位文件就添加好並可以使用了,使用方式直接選擇模擬器運行就可以。如果說GPX文件操作比較繁瑣和複雜,我們還可以使用模擬器的工具來進行定位修改,如圖:在這裏插入圖片描述
    在這裏插入圖片描述
    然後輸入目標經緯度就可以完成位置錄入了。

補充說明:

之前面試的時候談及耗電量優化,在新的API中,蘋果提供了單次定位請求的功能,也就是獲取一次位置信息,代碼:

[self.locaationManager requestLocation]

其實現邏輯是按照定位精確度從低到高進行排序,逐個進行定位。如果在有效時間內,定位到了精確度最好的位置,那麼就把對應的位置通過代理告知外界,如果獲取到的位置不是精確度最高的那個,也會在定位超時後,通過代理告訴我們。需要注意的是:必須實現代理的locationManager:didFailWithError:方法,不能與startUpdatingLocation方法同時使用。
實現如下:

// 代理方法,錯誤處理
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
    NSLog(@"%@",error);
    // 如果管理器未能獲取位置,可能是GPS或者網絡信號不可用等情況,這時候不要再繼續消耗性能
    // 停止更新位置
    [self.locaationManager stopUpdatingLocation];
}

好了這期的內容到這裏就結束了,下期就開講原生的MapKit,到時候直接是可視化的地圖定位信息,大傢伙期待嗎?~

下期內容:MapKit的實際應用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章