iOS-定位

一瞒渠、前言

大數(shù)據(jù)時代皮璧,用戶對自己的隱私安全越來越關(guān)注,所以遥巴,隨著iOS系統(tǒng)更新千康,蘋果對用戶隱私相關(guān)(定位、相冊铲掐、網(wǎng)絡(luò)吧秕、粘貼板等)權(quán)限控制持續(xù)升級。其中定位權(quán)限相關(guān)申請API與配置項較多迹炼,本文旨在記錄說明 iOS8.0 - 14.0beta 從權(quán)限申請到獲取定位數(shù)據(jù)流程砸彬。

內(nèi)容包括定位權(quán)限、獲取定位數(shù)據(jù)斯入、定位權(quán)限API調(diào)用實踐砂碉。定位權(quán)限模塊按照系統(tǒng)相關(guān)性分別介紹該系統(tǒng)下權(quán)限配置與API調(diào)用細(xì)節(jié)、注意事項與表格總結(jié)刻两;獲取定位數(shù)據(jù)模塊介紹定位關(guān)鍵參數(shù)增蹭、單次/連續(xù)定位等;調(diào)用實踐模塊介紹了從 iOS8.0 - 14.0beta 系統(tǒng)定位權(quán)限的適配實踐磅摹。

二滋迈、定位權(quán)限

1、iOS8.*

-前臺定位

-需要在info.plist配置NSLocationWhenInUseUsageDescription字段户誓;

-首次使用定位時饼灿,通過API接口requestWhenInUseAuthorization申請應(yīng)用使用時權(quán)限;

注意:此權(quán)限下帝美,如果Xcode勾選 Capabilities -> UIBackgroundModes > Location updates碍彭,則app退到后臺仍可獲取定位數(shù)據(jù),但此時在手機(jī)上方會有定位小藍(lán)條提示悼潭;

-后臺定位

-需要在info.plist配置NSLocationAlwaysUsageDescription字段庇忌;

-需要Xcode勾選 Capabilities -> UIBackgroundModes > Location updates;

-首次使用定位時舰褪,通過API接口requestAlwaysAuthorization申請應(yīng)用未使用時權(quán)限皆疹;

2、iOS9.與iOS10.

-****前臺定位****

-需要在info.plist配置NSLocationWhenInUseUsageDescription字段占拍;

-首次使用定位時略就,通過API接口requestWhenInUseAuthorization申請應(yīng)用使用時權(quán)限捎迫,如下圖;

image
 注意:此權(quán)限下残制,如果Xcode勾選 Capabilities -> UIBackgroundModes > Location updates并且allowsBackgroundLocationUpdates設(shè)為YES立砸,則app退到后臺仍可獲取定位數(shù)據(jù),但此時在手機(jī)上方會有定位小藍(lán)條提示初茶;

-****后臺定位****

-需要在info.plist配置NSLocationAlwaysUsageDescription字段颗祝;

-需要Xcode勾選 Capabilities -> UIBackgroundModes > Location updates;

-需要CLLocationManager設(shè)置allowsBackgroundLocationUpdates為YES恼布;

-首次使用定位時螺戳,通過API接口requestAlwaysAuthorization申請應(yīng)用未使用時權(quán)限,如下圖折汞;

image

-與iOS8.版本相比不同點***

-iOS9.后臺增加了allowsBackgroundLocationUpdates屬性倔幼,可以認(rèn)為在iOS8.下allowsBackgroundLocationUpdates永遠(yuǎn)為YES;

3爽待、iOS11.與iOS12.

-****前臺定位****

-需要在info.plist配置NSLocationWhenInUseUsageDescription字段损同;

-首次使用定位時,通過API接口requestWhenInUseAuthorization申請應(yīng)用使用時權(quán)限鸟款,如下圖膏燃;

image

注意:此權(quán)限下,如果Xcode勾選 Capabilities -> UIBackgroundModes > Location updates并且allowsBackgroundLocationUpdates設(shè)為YES何什,則app退到后臺仍可獲取定位數(shù)據(jù)组哩,但此時在手機(jī)上方會有定位小藍(lán)條提示,此小藍(lán)條不可隱藏处渣;

-****后臺定位****

-需要在info.plist配置NSLocationWhenInUseUsageDescription伶贰、NSLocationAlwaysAndWhenInUseUsageDescription字段;

-需要Xcode勾選 Capabilities -> UIBackgroundModes > Location updates罐栈;

-需要CLLocationManager設(shè)置allowsBackgroundLocationUpdates為YES黍衙;

-首次使用定位時,通過API接口requestAlwaysAuthorization申請應(yīng)用未使用時權(quán)限悠瞬,如下圖们豌;

image
 注意:此權(quán)限下,當(dāng)app在后臺時浅妆,系統(tǒng)默認(rèn)不展示定位小藍(lán)條,可通過showsBackgroundLocationIndicator控制小藍(lán)條是否顯示障癌;

-與iOS10.版本相比不同點***

-iOS11.*變更了后臺定位權(quán)限配置字段凌外;

-iOS11.*以后如果申請后臺定位,info.plist需要同時配置NSLocationWhenInUseUsageDescription涛浙、NSLocationAlwaysAndWhenInUseUsageDescription兩個字段康辑;

-iOS11.增加了showsBackgroundLocationIndicator屬性摄欲,當(dāng)擁有后臺定位權(quán)限時,用于控制定位小藍(lán)條是否顯示疮薇⌒厍剑可以認(rèn)為在iOS10.之前showsBackgroundLocationIndicator永遠(yuǎn)為NO;

4按咒、iOS13.*

-****前臺定位****

-需要在info.plist配置NSLocationWhenInUseUsageDescription字段迟隅;

-首次使用定位時,通過API接口requestWhenInUseAuthorization申請應(yīng)用使用時權(quán)限励七;

注意:權(quán)限申請彈窗與之前版本不一致智袭,新增了允許一次選項;如果用戶選擇允許一次后掠抬,下次在使用app時吼野,仍可重新調(diào)用API申請定位權(quán)限;如下圖

image

-****后臺定位****

-需要在info.plist配置NSLocationWhenInUseUsageDescription两波、NSLocationAlwaysAndWhenInUseUsageDescription字段瞳步;

-需要Xcode勾選 Capabilities -> UIBackgroundModes > Location updates;

-需要CLLocationManager設(shè)置allowsBackgroundLocationUpdates為YES腰奋;

-首次使用定位時单起,通過API接口requestAlwaysAuthorization申請權(quán)限;

 注意:1)直接調(diào)用requestAlwaysAuthorization申請權(quán)限時氛堕,權(quán)限彈窗與調(diào)用requestWhenInUseAuthorization一樣馏臭,如上圖,用戶只可以選擇應(yīng)用使用時或者只允許一次讼稚。不同點:當(dāng)選擇使用app時允許選項后括儒,狀態(tài)變更的回調(diào)為kCLAuthorizationStatusAuthorizedAlways;并且當(dāng)app退到后臺后锐想,系統(tǒng)會擇機(jī)彈窗提示用戶是否要升級權(quán)限為始終允許帮寻。如下圖:
image
2)如果想要在應(yīng)用使用期間彈窗申請始終允許,則需要先調(diào)用requestWhenInUseAuthorization赠摇,并且獲得應(yīng)用使用期間定位權(quán)限固逗,之后在調(diào)用requestAlwaysAuthorization則可彈窗申請始終允許,如下圖藕帜;(感覺不是太友好烫罩,不建議使用)
image

-與iOS12.版本相比不同點***

-使用應(yīng)用期間的定位權(quán)限增加了允許一次選項;

-不能直接申請后臺定位權(quán)限洽故,需要用戶先選擇應(yīng)用使用期間的定位權(quán)限后贝攒,在進(jìn)行權(quán)限升級;

5时甚、iOS14.*(beta版本)

-****前臺定位****

-需要在info.plist配置NSLocationWhenInUseUsageDescription字段隘弊;

-首次使用定位時哈踱,通過API接口requestWhenInUseAuthorization申請應(yīng)用使用時權(quán)限;

注意:權(quán)限申請彈窗與之前版本不一致梨熙,新增了精確位置開關(guān)开镣,新增了小地圖展示當(dāng)前位置;小地圖的顯示咽扇,支持在手機(jī)定位設(shè)置中選擇邪财,如果選擇關(guān)閉不顯示則手機(jī)中所有app都不顯示此小地圖。如下圖

image

-****后臺定位****

-需要在info.plist配置NSLocationWhenInUseUsageDescription肌割、NSLocationAlwaysAndWhenInUseUsageDescription字段卧蜓;

-需要Xcode勾選 Capabilities -> UIBackgroundModes > Location updates;

-需要CLLocationManager設(shè)置allowsBackgroundLocationUpdates為YES把敞;

-首次使用定位時弥奸,通過API接口requestAlwaysAuthorization申請權(quán)限;

-****新增精度權(quán)限****

-需要在info.plist配置NSLocationTemporaryUsageDescriptionDictionary奋早,如下:


<key>NSLocationTemporaryUsageDescriptionDictionary</key>

<dict>

  ExampleUsageDescription

  This app needs accurate location so it can verify that you are in a supported region.

  AnotherUsageDescription

  This app needs accurate location so it can show you relevant results.

</dict>

-新增屬性字段@property (nonatomic, readonly) CLAccuracyAuthorization accuracyAuthorization API_AVAILABLE(ios(14.0), macos(11.0), watchos(7.0), tvos(14.0))盛霎;可以獲取當(dāng)前的定位精度權(quán)限。

-在app已經(jīng)獲得定位權(quán)限之后耽装,并且當(dāng)前用戶選擇的是模糊定位愤炸,則允許應(yīng)用申請一次臨時精確定位權(quán)限,申請api為- (void)requestTemporaryFullAccuracyAuthorizationWithPurposeKey:(NSString )purposeKey completion:(void(^)(NSError ))completion; 其中purposeKey既為plist中配置字典中的key掉奄,可以有多個规个,對應(yīng)app中不同的定位需求場景;注意:**此API不能用于申請定位權(quán)限姓建,只能用于從模糊定位升級為精確定位诞仓;申請定位權(quán)限只能調(diào)用requestWhen或requestAlways,如果沒有獲得定位權(quán)限速兔,直接調(diào)用此API無效墅拭。如下圖

image

-如果app默認(rèn)不使用精確定位,則可以在info.plist中配置NSLocationDefaultAccuracyReduced字段涣狗,配置該字段后谍婉,申請定位權(quán)限的小地圖中不在有精確定位的開關(guān),即為關(guān)镀钓。如下面圖示

  -需要注意該字段類型為Boolean穗熬,如果為其他類型則不起效;

  -配置該字段后丁溅,申請定位權(quán)限的小地圖左上角則沒有精確開關(guān)死陆,默認(rèn)關(guān)閉,如下面圖示唧瘾。但是如果info.plist中配置了NSLocationTemporaryUsageDescriptionDictionary措译,則仍可以申請臨時的精確定位權(quán)限;

  -??:測試期間使用Xcode12 beta1到beta4饰序,直接使用info.plist的Property List添加NSLocationDefaultAccuracyReduced字段只能是string领虹,所以會造成不起效的問題,如果您也遇到類似問題求豫,可以點擊info.plist右鍵Open As -> Source Code塌衰,即使用源碼直接添加既可起效;

<key>NSLocationDefaultAccuracyReduced</key>

<true/>

[圖片上傳失敗...(image-24baae-1637218463749)]

-與iOS13.版本相比不同點***

-權(quán)限申請彈窗與之前版本不一致蝠嘉;

-新增精度權(quán)限相關(guān)plist設(shè)置最疆、授權(quán)、讀仍楦妗努酸;

-新增臨時一次從模糊定位升級精確定位API;

-新增定位權(quán)限變更回調(diào)杜恰;

6获诈、定位權(quán)限更新回調(diào)

-****iOS13.*及以前:****- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status;

-如主動獲取定位權(quán)限可使用類方法:+ (CLAuthorizationStatus)authorizationStatus心褐;

-CLAuthorizationStatus枚舉取值

typedef NS_ENUM(int, CLAuthorizationStatus) {

kCLAuthorizationStatusNotDetermined = 0, //用戶沒有決定是否使用定位服務(wù)

kCLAuthorizationStatusRestricted, //定位服務(wù)授權(quán)狀態(tài)受限制

kCLAuthorizationStatusDenied, //用戶拒絕/定位總開關(guān)關(guān)閉

kCLAuthorizationStatusAuthorizedAlways, //始終允許

kCLAuthorizationStatusAuthorizedWhenInUse, //在應(yīng)用使用期間

kCLAuthorizationStatusAuthorized //已經(jīng)廢棄舔涎,等同于始終允許

};

-iOS14.及以后***:- (void)locationManagerDidChangeAuthorization:(CLLocationManager *)manager;

-通過manager.authorizationStatus對象方法獲取當(dāng)前定位權(quán)限逗爹,此方法在iOS13及以前版本是類方法亡嫌;

-通過manager.accuracyAuthorization對象方法獲取當(dāng)前精度權(quán)限;

-CLAccuracyAuthorization枚舉取值

typedef NS_ENUM(NSInteger, CLAccuracyAuthorization) {

CLAccuracyAuthorizationFullAccuracy, //精確定位

CLAccuracyAuthorizationReducedAccuracy, //模糊定位

};

7掘而、總結(jié)

-****定位權(quán)限注意事項****

-iOS11以后如果申請后臺定位挟冠,info.plist需要同時配置NSLocationWhenInUseUsageDescription、NSLocationAlwaysAndWhenInUseUsageDescription兩個字段镣屹;

-調(diào)用申請定位權(quán)限API圃郊,在用戶抉擇后,再次調(diào)用無效女蜈;

-如果調(diào)用requestWhenInUseAuthorization申請過使用期間的定位權(quán)限持舆,并且得到用戶許可,則之后仍可調(diào)用requestAlwaysAuthorization申請一次后臺定位權(quán)限(即權(quán)限升級)伪窖;

-iOS13后逸寓,直接調(diào)用requestAlwaysAuthorization申請權(quán)限時,權(quán)限彈窗與調(diào)用requestWhenInUseAuthorization一樣覆山,在app進(jìn)入后臺后竹伸,系統(tǒng)會擇機(jī)彈窗提示用戶是否要權(quán)限升級為始終允許;

-自2019年下半年起,蘋果商店上架app對后臺定位權(quán)限增加限制勋篓,如果info.plist中不包含NSLocationAlwaysUsageDescription/NSLocationAlwaysAndWhenInUseUsageDescription字段吧享,則在app代碼中不能出現(xiàn)符號requestAlwaysAuthorization,否則上架審核不通過譬嚣;

-****Info.plist 中的字段總結(jié)****

| iOS版本 | NSLocationWhenInUseUsageDescription | NSLocationAlwaysUsageDescription | NSLocationAlwaysAndWhenInUseUsageDescription | NSLocationTemporaryUsageDescriptionDictionary |

| :---: | :---: | :---: | :---: | :---: |

| iOS 8 | YES | YES | × | × |

| iOS 9 | YES | YES | × | × |

| iOS 10 | YES | YES | × | × |

| iOS 11 | YES | × | YES | × |

| iOS 12 | YES | × | YES | × |

| iOS 13 | YES | × | YES | × |

| iOS 14 | YES | × | YES | YES |

-****不同系統(tǒng)版本調(diào)用定位權(quán)限API差異****

****iOS8.0****

| - | Capabilities 關(guān) | Capabilities 開 |

| :--- | :---: | :---: |

| requestAlwaysAuthorization | 可以前臺定位钢颂、不可以后臺定位、無藍(lán)條 | 可以前臺定位拜银、可以后臺定位殊鞭、無藍(lán)條 |

| requestWhenInUseAuthorization | 可以前臺定位、不可以后臺定位尼桶、無藍(lán)條 | 可以前臺定位操灿、可以后臺定位、有藍(lán)條 |

| 無/用戶拒絕 | 無任何定位 | 無任何定位 |

****iOS9.0 - iOS12.0****

| | Capabilities 關(guān) | | Capabilities 開 | |

| --- | :---: | :---: | --- | --- |

| | allowsBackgroundLocationUpdates關(guān) | allowsBackgroundLocationUpdates開 | allowsBackgroundLocationUpdates關(guān) | allowsBackgroundLocationUpdates開 |

| requestAlwaysAuthorization | 可以前臺定位泵督、不可以后臺定位趾盐、無藍(lán)條 | iOS拋出Crash | 可以前臺定位、不可以后臺定位幌蚊、無藍(lán)條 | 可以前臺定位谤碳、可以后臺定位、無藍(lán)條 |

| requestWhenInUseAuthorization | 可以前臺定位溢豆、不可以后臺定位蜒简、無藍(lán)條 | iOS拋出Crash | 可以前臺定位、不可以后臺定位漩仙、無藍(lán)條 | 可以前臺定位搓茬、可以后臺定位、有藍(lán)條 |

| 無/用戶拒絕 | 無任何定位 | iOS拋出Crash | 無任何定位 | 無任何定位 |

三队他、獲取定位數(shù)據(jù)

1卷仑、單次定位

-iOS8.0版本不支持單次定位,需要調(diào)用連續(xù)定位startUpdatingLocation接口麸折,自行實現(xiàn)單次定位功能锡凝;

-iOS9.0及以后版本,可以調(diào)用單次定位API:

-(void)requestLocation API_AVAILABLE(ios(9.0));

2垢啼、連續(xù)定位

-開始連續(xù)定位:- (void)startUpdatingHeading;

-停止連續(xù)定位:- (void)stopUpdatingHeading窜锯;

3、定位CLLocationManager相關(guān)屬性

-定位活動類型@property(assign, nonatomic) CLActivityType activityType;

-typedef NS_ENUM(NSInteger, CLActivityType) {

CLActivityTypeOther = 1, //未知類型芭析,默認(rèn)值

CLActivityTypeAutomotiveNavigation, //駕車導(dǎo)航定位

CLActivityTypeFitness,                        //健身活動锚扎,如步行、跑步馁启、騎車等驾孔;

CLActivityTypeOtherNavigation, //其他交通工具導(dǎo)航,如火車、輪船等

CLActivityTypeAirborne                       //空中飛行定位(iOS12及以上版本)

};

-設(shè)置期望的定位精度@property(assign, nonatomic) CLLocationAccuracy desiredAccuracy;

-當(dāng)精度設(shè)置較高時翠勉,定位服務(wù)會盡可能去獲取滿足desiredAccuracy的定位結(jié)果妖啥,但不一定會得到滿足期望的結(jié)果;

-kCLLocationAccuracyReduced為iOS14新特性眉菱,模糊定位迹栓,即使當(dāng)前精確定位開啟,如果設(shè)置該值俭缓,則會收到模糊定位結(jié)果;

-取值范圍:

kCLLocationAccuracyBestForNavigation; //導(dǎo)航高精度

kCLLocationAccuracyBest; //高精度

kCLLocationAccuracyNearestTenMeters; //10米

kCLLocationAccuracyHundredMeters; //100米

kCLLocationAccuracyKilometer; //1000米

kCLLocationAccuracyThreeKilometers; //3000米

kCLLocationAccuracyReduced; //模糊定位酥郭,誤差5000米(iOS14及以上版本)

-設(shè)置定位的最小更新距離@property(assign, nonatomic) CLLocationDistance distanceFilter;

-單位米华坦,默認(rèn)為 kCLDistanceFilterNone,表示只要檢測到設(shè)備位置發(fā)生變化就會更新位置信息不从;

-@property(nonatomic, assign) BOOL pausesLocationUpdatesAutomatically;

-是否允許系統(tǒng)自動暫停定位功能惜姐,設(shè)置為YES進(jìn)行后臺定位時,系統(tǒng)檢測到長時間沒有位置更新的時候椿息,將會暫停定位功能歹袁,當(dāng)app進(jìn)入前臺時會恢復(fù)定位功能;

3寝优、定位數(shù)據(jù)更新回調(diào)

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

didUpdateLocations:(NSArray *)locations;

-locations是按時間排序的CLLocation對象數(shù)組条舔,一般使用lastObject即為當(dāng)前最新定位信息;

四乏矾、定位權(quán)限API調(diào)用實踐

1孟抗、配置info.plist

-如果不需要使用后臺定位,則無需配置NSLocationAlwaysAndWhenInUseUsageDescription钻心、NSLocationAlwaysUsageDescription字段凄硼,并且代碼(包括使用的靜態(tài)庫)中不能出現(xiàn)requestAlwaysAuthorization符號;

[圖片上傳失敗...(image-3fd3da-1637218463749)]

2捷沸、開始定位

-此處直接在主線程開始定位摊沉,如果需要在子線程開始定位,則需要開啟子線程的runloop痒给,此處不再累述说墨。自蘋果X后,如果在子線程開始定位侈玄,會有UI不在主線程調(diào)用的警告婉刀,直接屏蔽或者忽略即可,不影響正常使用序仙;


//前置步驟:創(chuàng)建定位管理類CLLocationManager突颊,配置定位參數(shù)

//開始定位

- (void)startLocation{

//self.locationManager = [[CLLocationManager alloc]init];

//self.locationManager.allowsBackgroundLocationUpdates = YES;

//self.locationManager.delegate = self;

    if([self locationServiceIsValid] == NO){

        NSLog(@"用戶拒絕該app使用定位服務(wù)");

        return;

    }

    //該場景下是否需要精確定位

    BOOL isNeedFullAccuracy = YES;

    //該場景下如果需要精確定位,則對應(yīng)的plist中配置的key

    NSString *purposeKey = @"ExampleUsageDescription";

    //判斷當(dāng)前定位權(quán)限是否ok

    [self checkLocationAuthorizationStatus:self.locationManager

                           needFullAccuracy:isNeedFullAccuracy

                                 purposeKey:purposeKey];

    //開始連續(xù)定位

    [self.locationManager startUpdatingLocation];

}

3、獲取當(dāng)前定位權(quán)限


//獲取當(dāng)前定位權(quán)限

- (CLAuthorizationStatus)authorizationStatus

{

    if (@available(iOS 14.0, *)) {

        return self.locationManager.authorizationStatus;

    } else {

        return [CLLocationManager authorizationStatus];

    }

}

//當(dāng)前應(yīng)用是否可以使用/申請定位服務(wù)

- (BOOL)locationServiceIsValid{

    if ([self authorizationStatus] == kCLAuthorizationStatusDenied ||

        [self authorizationStatus] == kCLAuthorizationStatusRestricted) {

        return NO;

    }

    return YES;

}

//當(dāng)前定位狀態(tài)是否可用

- (BOOL)locationAuthStatusIsValid{

    if ([self locationServiceIsValid] == NO) {

        return  NO;

    }

    if ([self authorizationStatus] == kCLAuthorizationStatusNotDetermined) {

        return NO;

    }

    return YES;

}

4律秃、核實當(dāng)前權(quán)限狀態(tài)爬橡,判斷是否需要申請權(quán)限或者權(quán)限升級

-****如果app需要使用后臺定位****


//核實當(dāng)前權(quán)限狀態(tài),判斷是否需要申請權(quán)限或者權(quán)限升級

- (void)checkLocationAuthorizationStatus:(CLLocationManager *)manager

                         needFullAccuracy:(BOOL)isNeedFullAccuracy

                                purposeKey:(NSString *)purposeKey{

      if([self authorizationStatus] == kCLAuthorizationStatusNotDetermined){

          //如果沒有定位權(quán)限棒动,則需要先申請定位權(quán)限

          //如果是iOS14申請權(quán)限彈窗時可以選擇精度開關(guān)吼虎,所以不用在單獨處理精度權(quán)限

          [self requestLocationAuthorizationIfNeed:manager];

      }else if(isNeedFullAccuracy){

          //如果已經(jīng)有定位權(quán)限且需要精確定位

            [self requestTemporaryFullAccuracyAuthorizationIfNeed:manager purposeKey:purposeKey];

      }

}

//如果當(dāng)前場景需要精確定位,則可以申請一次臨時精確定位

- (void)requestTemporaryFullAccuracyAuthorizationIfNeed:(CLLocationManager *)manager

                                             purposeKey:(NSString *)purposeKey

{

    //如果是非iOS14系統(tǒng)填硕,則默認(rèn)為精確定位

    if (@available(iOS 14.0, *)) {

        //如果已經(jīng)獲得定位權(quán)限擂错,但精度權(quán)限只是模糊定位

        if (manager.accuracyAuthorization == CLAccuracyAuthorizationReducedAccuracy) {

            NSDictionary *locationTemporaryDictionary = [[NSBundle mainBundle]

                        objectForInfoDictionaryKey:@"NSLocationTemporaryUsageDescriptionDictionary"];

            BOOL hasLocationTemporaryKey = locationTemporaryDictionary != nil && locationTemporaryDictionary.count != 0;

            if (hasLocationTemporaryKey) {

                //此API不能用于申請定位權(quán)限,只能用于從模糊定位升級為精確定位粱锐;申請定位權(quán)限只能調(diào)用

                //requestWhen或requestAlways疙挺,如果沒有獲得定位權(quán)限,直接調(diào)用此API無效怜浅。

                [manager requestTemporaryFullAccuracyAuthorizationWithPurposeKey:purposeKey completion:nil];

            }else{

                NSLog(@"如果需要使用臨時精確定位铐然,需要在Info.plist中添加 \

                NSLocationTemporaryUsageDescriptionDictionary字段。");

            }

        }

    }

 }

//請求定位權(quán)限恶座,

- (void)requestLocationAuthorizationIfNeed:(CLLocationManager *)manager

{

    //系統(tǒng)版本號

    CGFloat systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];

    //系統(tǒng)版本8+ && 沒有選擇過定位權(quán)限

    if (systemVersion > 7.99 && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined)

    {

        //獲取info.plist中配置字段信息

        BOOL hasAlwaysKey = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"] != nil;

        BOOL hasWhenInUseKey = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"] != nil;

        BOOL hasAlwaysAndWhenInUseKey = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysAndWhenInUseUsageDescription"] != nil;

        //如果是iOS11及以后版本搀暑。(當(dāng)前iOS11到13居多)

        if (@available(iOS 11.0, *)){

            if (hasAlwaysAndWhenInUseKey && hasWhenInUseKey)

            {

                //如果plist同時配置兩個字段,則兩個權(quán)限申請API都可以調(diào)用跨琳;

                //建議直接調(diào)用requestAlwaysAuthorization即可

                [manager requestAlwaysAuthorization];

            }

            else if (hasWhenInUseKey)

            {

                //如果plist只配置InUseKey自点,則只能調(diào)用使用時API

                [manager requestWhenInUseAuthorization];

            }

            else{

                NSLog(@"要在iOS11及以上版本使用定位服務(wù), 需要在Info.plist中添加 \

                NSLocationAlwaysAndWhenInUseUsageDescription和NSLocationWhenInUseUsageDescription字段。");

            }

        }

        else

        {

            if (hasAlwaysKey)

            {

                //如果plist配置hasAlwaysKey湾宙,則可以調(diào)用始終允許API

                [manager requestAlwaysAuthorization];

            }

            else if (hasWhenInUseKey)

            {

                //如果plist配置hasAlwaysKey樟氢,則可以調(diào)用始終允許API

                [manager requestWhenInUseAuthorization];

            }

            else

            {

                NSLog(@"要在iOS8到iOS10版本使用定位服務(wù), 需要在Info.plist中添加 \

                NSLocationAlwaysUsageDescription或者NSLocationWhenInUseUsageDescription字段。");

            }

        }

    }

}

-****如果app不需要使用后臺定位****


//核實當(dāng)前權(quán)限狀態(tài)侠鳄,判斷是否需要申請權(quán)限或者權(quán)限升級

- (void)checkLocationAuthorizationStatus:(CLLocationManager *)manager

                         needFullAccuracy:(BOOL)isNeedFullAccuracy

                                purposeKey:(NSString *)purposeKey{

      if([self authorizationStatus] == kCLAuthorizationStatusNotDetermined){

          //如果沒有定位權(quán)限埠啃,則需要先申請定位權(quán)限

          //如果是iOS14申請權(quán)限彈窗時可以選擇精度開關(guān),所以不用在單獨處理精度權(quán)限

          [self requestLocationAuthorizationIfNeed:manager];

      }else if(isNeedFullAccuracy){

          //如果已經(jīng)有定位權(quán)限且需要精確定位

            [self requestTemporaryFullAccuracyAuthorizationIfNeed:manager purposeKey:purposeKey];

      }

}

//如果當(dāng)前場景需要精確定位伟恶,則可以申請一次臨時精確定位

- (void)requestTemporaryFullAccuracyAuthorizationIfNeed:(CLLocationManager *)manager

                                             purposeKey:(NSString *)purposeKey

{

    //如果是非iOS14系統(tǒng)碴开,則默認(rèn)為精確定位

    if (@available(iOS 14.0, *)) {

        //如果已經(jīng)獲得定位權(quán)限,但精度權(quán)限只是模糊定位

        if (manager.accuracyAuthorization == CLAccuracyAuthorizationReducedAccuracy) {

            NSDictionary *locationTemporaryDictionary = [[NSBundle mainBundle]

                        objectForInfoDictionaryKey:@"NSLocationTemporaryUsageDescriptionDictionary"];

            BOOL hasLocationTemporaryKey = locationTemporaryDictionary != nil && locationTemporaryDictionary.count != 0;

            if (hasLocationTemporaryKey) {

                //此API不能用于申請定位權(quán)限博秫,只能用于從模糊定位升級為精確定位潦牛;申請定位權(quán)限只能調(diào)用

                //requestWhen或requestAlways,如果沒有獲得定位權(quán)限挡育,直接調(diào)用此API無效巴碗。

                [manager requestTemporaryFullAccuracyAuthorizationWithPurposeKey:purposeKey completion:nil];

            }else{

                NSLog(@"如果需要使用臨時精確定位,需要在Info.plist中添加 \

                NSLocationTemporaryUsageDescriptionDictionary字段即寒。");

            }

        }

    }

 }

//請求定位權(quán)限橡淆,

- (void)requestLocationAuthorizationIfNeed:(CLLocationManager *)manager

{

    //系統(tǒng)版本號

    CGFloat systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];

    //系統(tǒng)版本8+ && 沒有選擇過定位權(quán)限

    if (systemVersion > 7.99 && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined)

    {

        //獲取info.plist中配置字段信息

        BOOL hasWhenInUseKey = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"] != nil;

        if (hasWhenInUseKey)

        {

            //如果plist配置InUseKey召噩,則只能調(diào)用使用時API

            [manager requestWhenInUseAuthorization];

        }

        else{

            NSLog(@"要在iOS8及以上版本使用定位服務(wù), 需要在Info.plist中添加 \

            NSLocationWhenInUseUsageDescription字段。");

        }

    }

}

5逸爵、定位權(quán)限狀態(tài)變更


//iOS13及以前版本回調(diào)

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status

{

    [self locationStatusDidChanged:[CLLocationManager authorizationStatus]];

}

//iOS14及以后版本回調(diào)

- (void)locationManagerDidChangeAuthorization:(CLLocationManager *)manager

{

    if (@available(iOS 14.0, *)) {

        [self locationStatusDidChanged:manager.authorizationStatus];

        if([self locationAuthStatusIsValid]){

            CLAccuracyAuthorization accuracyAuth = manager.accuracyAuthorization;

            if (accuracyAuth == CLAccuracyAuthorizationReducedAccuracy){

                NSLog(@"TODO: 可以模糊定位");

            }else{

                NSLog(@"TODO: 可以精確定位");

            }

            //該場景下是否需要精確定位

            BOOL isNeedFullAccuracy = YES;

            if (isNeedFullAccuracy == YES && accuracyAuth == CLAccuracyAuthorizationReducedAccuracy) {

                NSLog(@"TODO: 該場景需要精確定位才可以使用具滴,請去設(shè)置中打開精確定位開關(guān)");

            }

        }

    } else {

    }

}

- (void)locationStatusDidChanged:(CLAuthorizationStatus)authStatus

{

    switch (authStatus) {

        case kCLAuthorizationStatusNotDetermined:

            NSLog(@"可以申請定位權(quán)限");

            break;

        case kCLAuthorizationStatusRestricted:

        case kCLAuthorizationStatusDenied:

            NSLog(@"TODO: 沒有定位權(quán)限");

            break;

        case kCLAuthorizationStatusAuthorizedAlways:

        case kCLAuthorizationStatusAuthorizedWhenInUse:

            NSLog(@"TODO: 擁有定位權(quán)限");

        default:

            break;

    }

}

6、定位回調(diào)


//定位回調(diào)

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations

{

    CLLocation *locationg = locations.lastObject;

    NSLog(@"TODO: 收到定位數(shù)據(jù):%@",locationg);

}

五师倔、小結(jié)

定位信息作為用戶非常在意的隱私數(shù)據(jù)构韵,iOS開發(fā)者應(yīng)盡量遵循適用原則(即能滿足需求的最小權(quán)限)去獲取用戶定位信息。本文對iOS系統(tǒng)定位權(quán)限說明從8.0到14.0趋艘,其中關(guān)于API調(diào)用實踐是對應(yīng)的最大定位權(quán)限疲恢,開發(fā)者可以根據(jù)需求參考相對應(yīng)的部分。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末致稀,一起剝皮案震驚了整個濱河市冈闭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌抖单,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件遇八,死亡現(xiàn)場離奇詭異矛绘,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)刃永,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門货矮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人斯够,你說我怎么就攤上這事囚玫。” “怎么了读规?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵抓督,是天一觀的道長。 經(jīng)常有香客問我束亏,道長铃在,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任碍遍,我火速辦了婚禮定铜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘怕敬。我一直安慰自己揣炕,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布东跪。 她就那樣靜靜地躺著畸陡,像睡著了一般鹰溜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上罩锐,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天奉狈,我揣著相機(jī)與錄音,去河邊找鬼涩惑。 笑死仁期,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的竭恬。 我是一名探鬼主播跛蛋,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼痊硕!你這毒婦竟也來了赊级?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤岔绸,失蹤者是張志新(化名)和其女友劉穎理逊,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盒揉,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡晋被,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了刚盈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片羡洛。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖藕漱,靈堂內(nèi)的尸體忽然破棺而出欲侮,到底是詐尸還是另有隱情,我是刑警寧澤肋联,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布威蕉,位于F島的核電站,受9級特大地震影響牺蹄,放射性物質(zhì)發(fā)生泄漏忘伞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一沙兰、第九天 我趴在偏房一處隱蔽的房頂上張望氓奈。 院中可真熱鬧,春花似錦鼎天、人聲如沸舀奶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽育勺。三九已至但荤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間涧至,已是汗流浹背腹躁。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留南蓬,地道東北人纺非。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像赘方,于是被迫代替她去往敵國和親烧颖。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容