iOS-CLLocationManager請求獲取使用者定位時,是否要先判斷使用者之前有沒有同意過?

Lebus發表於2019-04-22

先上一段熟悉的程式碼提提神:)

import CoreLocation
let locationManager = CLLocationManager()
locationManager.delegate = self
...
locationManager.requestLocation()
複製程式碼

比如說在做一款天氣App的時候,我們首先需要請求使用者的位置(locationManager.requestLocation()),然後系統就自動呼叫func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {...}delegate方法,然後我們在這個方法的locations引數裡面獲取到使用者的位置資訊。

那大家就在想啊,在requestLocation()的時候是不是先要判斷一下之前使用者是不是已經同意過了呢?要不要加個if else判斷什麼的呢?

按正常邏輯是這樣的,沒錯!

但在iOS的世界裡(別的語言也是),對於使用者同不同意有個專屬名詞--授權。 蘋果一直很重視使用者隱私,所以我們開發的任何一款App一旦想要窺探使用者隱私(比如這裡的定位)的時候,都需要向使用者發起明確請求,並獲得授權才行。

那對啊,不應該就是在上面的requestLocation()的時候判斷一下嘛?

error!

其實這裡有個小小的障眼誤解,就是這個requestLocation()的作用---他並不是請求使用者授權的意思。 ---問題就出在這裡。

他的真正作用是:

官方的說法是:只請求一次使用者的位置。

翻譯成人話就是說只呼叫一次func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {...}方法,和授不授權沒有半毛錢關係,(令人震驚的英文名稱)。 這個requestLocation()還有個同宗兄弟,叫startUpdatingLocation()官方解釋---我們呼叫幾次,他就呼叫幾次func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {...}方法,也就是說可以按需使用(比如電商和外賣App讓我們填收貨地址的時候)。

搞了半天,那真正的請求使用者授權的方法是哪個?

就兩個:

requestWhenInUseAuthorization() requestAlwaysAuthorization() 他們都是用例項化後的CLLocationManager進行呼叫,從字面上就能知道是什麼意思了,根據專案需求使用就行,官方不推薦使用第二個除非特殊情況(也就是說上架稽核的時候會很嚴)。

那就是說我們重點討論第一個就行了。

進入正題:

我們首先用CLLocationManager下面的一個常量屬性CLAuthorizationStatus來判斷當前使用者是否已授權(有沒有同意被定位):

因為是常量屬性,所以直接用CLLocationManager.authorizationStatus()就可以(呼叫authorizationStatus()函式才能返回這個常量屬性CLAuthorizationStatus),不需要例項化CLLocationManager

一共有五種狀態來判斷使用者的授權情況:

//在合適的地方使用以下程式碼
switch CLLocationManager.authorizationStatus() {
      case .notDetermined://使用者第一次開啟App的時候
         //請求使用者大人同意我定位
         locationManager.requestWhenInUseAuthorization()
         break//跳出switch

      // .restricted--這臺iPhone或iPad被開啟了父母限制   
      // .denied--使用者拒絕+使用者在設定裡關閉了定位服務(或飛航模式)
      // (接上)可以用CLLocationManager.locationServicesEnabled()來判斷是哪種拒絕
      case .restricted, .denied:
         //既然被拒絕了,那就不給你用一些需要定位才能實現的功能啦
         //或根據不同情況給使用者良好的提示,引導使用者去同意被定位
         disableMyLocationBasedFeatures()
         break
            
      //使用者已授權(已同意被定位)
      case .authorizedWhenInUse, .authorizedAlways:
         //開啟美妙功能
         enableMyWhenInUseFeatures()
         break
      }
複製程式碼

熟悉iOS的人都知道,只要一有個動作發生(比如我們這裡的授權請求),一定會有個人在下面接著(delegate方法)。

比如說: 1.用上面的程式碼進行判斷之後,我們彈出了請求使用者授權的彈框,使用者呢,或被你說動了同意了定位服務,或被你的醜陋介面氣到拒絕被定位等等等的時候,我們該做出什麼樣的應對呢? 2.使用者或手動設定隱私或切換飛航模式,導致iPhone或iPad設定中的定位服務由無到有,有有到無的時候,我們該怎麼辦呢?

一旦使用者怎麼怎麼樣我們要怎麼怎麼樣--delegate!

一旦使用者的CLAuthorizationStatus改變就會呼叫didChangeAuthorization方法:

func locationManager(_ manager: CLLocationManager, 
                      didChangeAuthorization status: CLAuthorizationStatus) {
   switch status {
      case .restricted, .denied:
         //可照上面一樣再進行細分判斷
         disableMyLocationBasedFeatures()
         break
            
      case .authorizedWhenInUse:
         //皆大歡喜
         enableMyWhenInUseFeatures()
         break
                  
      case .notDetermined, .authorizedAlways:
         //不在本話題範圍內就先不管了
         break
   }
}
複製程式碼

以上。

想學習更多關於iOS的定位功能,可以去看一下我的視訊教程 :)

感謝APPLE官方對本文的大力支援。

相關文章