iOS14でのCore Location変更点

# iOS14でのCore Location

こんにちは、今回は業務でiOS14で変更になったCore Location周りの改修をしたので、備忘録的に書かせていただきます。
あんまり記事がなかったので、誰かの役に立てば幸いです！

## 環境
macOS Catalina 10.15.6
Xcode Version 12.0.1

## Deprecated

まずDeprecatedになったものを調査しました。
対象は今回iOS14だと使えない物についてまとめます。


### CLLocationManager
#### Requesting Authorization for Location Services
- authorizationStatus()

```swift 
class func authorizationStatus() -> CLAuthorizationStatus
// 位置情報サービスを利用するためのアプリの認証状況を返します。
```
#### Initiating Beacon Ranging Requests

```swift
func startRangingBeacons(in: CLBeaconRegion)
// 指定されたビーコン領域の通知の配信を開始します。

func stopRangingBeacons(in: CLBeaconRegion)
// 指定されたビーコン領域の通知の配信を停止します。

var rangedRegions: Set<CLRegion>
// 指定されたビーコン領域の通知の配信を停止します。
```

#### Deferring Location Updates
```swift
class func deferredLocationUpdatesAvailable() -> Bool
// デバイスが遅延ロケーション更新をサポートするかどうかを示すブール値を返します。

func allowDeferredLocationUpdates(untilTraveled: CLLocationDistance, timeout: TimeInterval)
// 指定された基準が満たされるまで、ロケーション更新の配信を延期するようにロケーションマネージャーに依頼します。

func disallowDeferredLocationUpdates()
// このアプリの位置情報の更新の延期をキャンセルします。
```


### CLLocationManagerDelegate

#### Responding to Authorization Changes

- Deprecated

```swift
func locationManager(CLLocationManager, didChangeAuthorization: CLAuthorizationStatus)
// アプリがロケーションマネージャーを作成したとき、および承認ステータスが変更されたときに、代理人に承認ステータスを通知します
```

- New

```swift
func locationManagerDidChangeAuthorization(CLLocationManager)
// アプリがロケーション マネージャを作成したとき、および承認ステータスが変更されたときに、委任者に通知します。
```

#### Responding to Ranging Events


- Deprecated 

```swift 
func locationManager(CLLocationManager, didRangeBeacons: [CLBeacon], in: CLBeaconRegion)
// 1つ以上のビーコンが範囲内にあることをデリゲートに通知します。
```

```swift

func locationManager(CLLocationManager, rangingBeaconsDidFailFor: CLBeaconRegion, withError: Error)
// 一連のビーコンのレンジング情報の収集中にエラーが発生したことをデリゲートに通知します。
```


ビーコン周りが結構変変更されてましたね。
余談ですが、
CLBeacon使ったことないし、何ができるかもわからんので、今度CLBeacon周り深く探ってみようかと思います。
登山とかするので、何かの役に立つかもしれないw


## 本題

さてさて、ここからは本題ですが、
今回のアップデートで特に注目されていたところとしては、
位置情報の許可をするときに、

- 正確な位置情報

項目が追加さてたのが大きな変更かなと個人的には思っています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403613/77ac91a5-0fd6-b7f4-40d5-81ff12c5efab.png" width="320">

なぜこうなったのかは、Appleさんがいろいろ考えてくれた感じなので、それは調べていただければ良いので、
今回はこの
- 正確な位置情報
に関して、Codeを踏まえて説明できたらと思います。

### 実装

これまでよくあった実装としては

```swift
let status = CLLocationManager.authorizationStatus() 
    switch status {
    case .authorizedWhenInUse:
    // ...
    case .authorizedAlways:
    // ... 
    case .denied:
    // ...
    case .notDetermined:
    // ...
    case .restricted:
    // ...
    case .authorized:
    // ...
```

こんな感じで　statusごとの処置を書いていたと思いますが

> 'authorizationStatus()' was deprecated in iOS 14.0


```swift
    @available(iOS, introduced: 4.2, deprecated: 14.0)
    open class func authorizationStatus() -> CLAuthorizationStatus
```

となっていたので、authorizationStatus()は使えません。
ただし

```swift
public enum CLAuthorizationStatus : Int32 {}
```
こちらは使えますので、間違えないようにしたいですね。

こちらの変更としては

```swift
open class CLLocationManager : NSObject {
    // ...
    @available(iOS 14.0, *)
    open var authorizationStatus: CLAuthorizationStatus { get }
}
```

CLLocationManager に　authorizationStatus　が新たに追加された形となりました。

ここ、ややこしいので、気をつけておいた方が良さそうです。

下記Codeは　CLLocationManagerの主な変更部分です。

```swift

open class CLLocationManager : NSObject {
    // ...
    @available(iOS 14.0, *)
    open var authorizationStatus: CLAuthorizationStatus { get }

    @available(iOS, introduced: 4.2, deprecated: 14.0)
    open class func authorizationStatus() -> CLAuthorizationStatus

    @available(iOS 14.0, *)
    open var accuracyAuthorization: CLAccuracyAuthorization { get }
    // アプリが使用を許可されている位置精度のレベルを示す値。

    @available(iOS 14.0, *)
    open var isAuthorizedForWidgetUpdates: Bool { get }
    // ウィジェットが位置の更新を受信する資格があるかどうかを示すブール値。

    @available(iOS 14.0, *)
    open func requestTemporaryFullAccuracyAuthorization(withPurposeKey purposeKey: String, completion: ((Error?) -> Void)? = nil)
    // 位置情報サービスを完全に正確に一時的に使用するためのユーザーの許可を要求します。

    @available(iOS 14.0, *)
    open func requestTemporaryFullAccuracyAuthorization(withPurposeKey purposeKey: String)
    // 位置情報サービスを完全に正確に一時的に使用するためのユーザーの許可を要求します。
}
```


ステータスの処理を分ける場合

> func locationManager(CLLocationManager, didChangeAuthorization: CLAuthorizationStatus) {}

こちらがdeprecatedなので

> func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {}

を使って実装していきます。

```swift
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
 let status = manager.authorizationStatus
 switch status {
   case .authorizedAlways, .authorizedWhenInUse:
   // ...
   case .notDetermined, .denied, .restricted:
   // ...
   default: 
   // ...
 }
}
```
このような形でstatusに対する処理を分岐する形となります。

次に正確な位置情報についてです

```swift
public enum CLAccuracyAuthorization : Int {
    case fullAccuracy = 0     // 正確な位置情報　ON
    case reducedAccuracy = 1  // 正確位置情報　　OFF
}
```
こちらが新規追加されました。

```swift
   switch manager.accuracyAuthorization {
   case .fullAccuracy:
       print("正確な位置情報")
   case .reducedAccuracy:
       print("曖昧な位置情報")
   default:

   }
```
実装としてはこのような形で分岐することが可能です。
非エンジニアの方に今回の変更を説明する場合
reducedAccuracyを[曖昧な位置情報]という言い方で説明したところ、理解してくれました。
公式によると　
(DeepL翻訳)
> // The user has chosen to grant this application access to location information with reduced accuracy.
    // Region monitoring and beacon ranging are not available to the application.  Other CoreLocation APIs
    // are available with reduced accuracy. 
    // Location estimates will have a horizontalAccuracy on the order of about 5km.  To achieve the
    // reduction in accuracy, CoreLocation will snap location estimates to a nearby point which represents
    // the region the device is in.  Furthermore, CoreLocation will reduce the rate at which location
    // estimates are produced.  Applications should be prepared to receive locations that are up to 20
    // minutes old.

 > ユーザーはこのアプリケーションに、精度を落とした位置情報へのアクセスを許可することを選択しました。
    地域モニタリングやビーコン測距はアプリケーションでは利用できません。 その他の CoreLocation API
    は精度を落として利用できます。
    位置推定の水平精度は約5kmのオーダーになります。 を達成するために
    精度の低下を防ぐために、 // CoreLocation は位置推定値を近くの点にスナップします。
    デバイスが存在する地域を指定します。 さらに、CoreLocation は、デバイスが存在する地域の
    見積もりを作成しています。 アプリケーションは、20までの場所を受信するために準備してください。
    分経過しています。


こんな感じで書いてあります。

業務で修正した主なところとしては正確な位置情報を取得して、いろいろと使っていたので、今回はここの修正を主に行いました。

## まとめ
今回はCoreLocationの変更された部分にフォーカスして書かせていただきました。
アプリによっていろんなパターンがあるので、一概に上記の対応だけでは望める実装ができない場合があるかと思いますので、私が参考にした記事を貼り付けておきます。

[iOS 14 でさらに強化された位置情報まわりのプライバシー](https://qiita.com/koogawa/items/6d2b7c50fd1917d8983e)
[[iOS14]WWDC 2020 Core Location 新要素 Preciseについて](https://qiita.com/satoru_pripara/items/7dbaf59dc840d679751c)


上記の記事を参考にいたしました。
この記事では書いていない
- requestTemporaryFullAccuracyAuthorizationの使い方
- info.plistについて
- AppleのMapアプリに関すること
- 標準アプリの挙動など
- 他諸々
などが記載されていたので、まとめて読んでおくと良さそうに思いました。

 Apple公式
[What's new in location](https://developer.apple.com/videos/play/wwdc2020/10660/)
[Core Location](https://developer.apple.com/documentation/corelocation)


読んでいただきありがとうございました。