iOS13から位置情報の権限周りの挙動が変わるかも

**本記事は[公開済みのドキュメント](https://developer.apple.com/videos/play/wwdc2019/705/)を元に作成しています。今後仕様変更などにより記載内容と異なる場合があります。予めご了承ください。**
そして間違ってたところがあったら指摘していただけるとめちゃ嬉しいです

WWDC2019ではSwiftUIやらProject Catalystなど興味深い話題がたくさん出ましたが、その影で（？）iOS13の位置情報権限周りで挙動が結構変わっていたので軽くまとめました。

## 何が変わったのか
- 位置情報の許可を求める画面では「常に許可」が選べなくなった
  - 代わりに「1度だけ許可する」が追加された
- `requestAlwaysAuthorization`を呼び出した時の挙動が変わった
  - 最初のポップアップで「使用中のみ許可」を選択すると、「仮の常に許可」が帰ってくるようになった
- モニタリング系APIは「常に許可」である必要がなくなった
  - Beaconや大まかな位置情報の利用ハードルが若干低くなった。

## つまり？
**「常に許可」のハードルが高くなった**

## 位置情報の許可を求める画面で「常に許可」が選べなくなった
iOS12では位置情報を取得する際に表示される選択肢は「常に許可」「アプリを使用中のみ許可」「拒否」の3つだったのですが、
iOS13からは「アプリを使用中は許可」「1度だけ許可」「拒否」となり、**「常に許可」が選べなくなりました。**
![705_whats_new_in_core_location-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186419/4f115b16-c8b2-bc7b-b87a-6ac061c5feb4.png)
*[What's New in Core Location](https://developer.apple.com/videos/play/wwdc2019/705/)より引用*

それぞれを選択した時の挙動も今までと異なります。
### アプリを使用中は許可を選択した場合
リクエストする権限によって挙動が異なります。

#### `requestWhenInUseAuthorization`で呼び出した場合
いつも通りアプリが使用中のみ位置情報の取得が可能です。
アプリ側には`.authorizedWhenInUse`としてステータスが返ります。

#### `requestAlwaysAuthorization`で呼び出した場合
位置情報の試用期間に入ります。
ユーザーは「アプリを使用中は許可」として選択していますが、アプリ側には`.authorizedAlways`として返ります。(WWDC2019の動画では、**仮の常に許可**として説明されています)

iOSはこの試用期間中、どこかユーザーが忙しくないタイミングでユーザーに対して**1回だけ**「使用中のみ許可」するか「常に許可」するかを聞いてきます。

![705_whats_new_in_core_location-14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186419/9d630ddb-aef7-cd3f-49de-b69d0641bc5b.png)
*[What's New in Core Location](https://developer.apple.com/videos/play/wwdc2019/705/)より引用*

ここでユーザーは位置情報の取得をアプリ使用中のみにすることも可能ですし、そのままにすることもできます。

ここまで見てわかるように、iOS13では真の「常に許可」にたどり着くまでのハードルが高くなっています。

今までは最初のポップアップで常に選択を選ばせれば良かったのですが、**真の常に許可を得るためには1段階手順を踏まないといけない**ことと、ユーザーの選択次第でアプリを使用中のみに戻される可能性があります。

今まで位置情報の取得は「常に許可」しか許されなかった系アプリ(位置情報共有アプリとかそうですね)は、
アプリを使用中のみでも動作するように修正するか、ユーザーに設定から「常に許可」を選択するよう促す必要がありそうです。

### 「1度だけ許可する」が押された場合
iOS13から新しく追加された選択肢です。
選択すると、アプリに対しては**「アプリを使用中のみ許可」と同じステータス(`.authorizedWhenInUse`)**が返ります。
なので、ステータスからは1度だけ許可しているかどうかは判断ができません。

また一時的な許可としての扱いなので、バックグラウンドに遷移してからしばらくする、あるいは次回起動時には**権限が決まっていない状態に戻ります。**

注意するべきなのが、**バックグラウンドに遷移してからしばらくすると権限が戻る点**です。
バックグラウンドで継続的に位置情報を要求している場合(`allowsBackgroundLocationUpdates = true`)は戻らないので問題ないのですが、
そうでない場合は、**位置情報を取得する際に毎回現在の権限をチェックする必要があります。**
特に、位置情報の権限をアプリ起動時、特定のタイミングでしかリクエストしていなかった場合は結構つらみが深いですね。。。

#### 結局どういうこと？
![705_whats_new_in_core_location-32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186419/28854be9-d361-9efa-f2f7-fd21b40b41c1.png)
*[What's New in Core Location](https://developer.apple.com/videos/play/wwdc2019/705/)より引用*

こういうことらしいです。

## モニタリング系APIは「常に許可」である必要がなくなった
iOS13では常に許可のハードルが高くなってしまった代わりに、今まで常に許可でないと使えなかったリージョン検知や、大まかな位置情報の変更の検知がアプリを使用中のみでも使用できるようになっています。

今まではワンショットで位置情報が欲しい場合は`.authorizedWhenInUse`を、リージョン系を使うなら`.authorizedAlways`と機能ごとに必要な権限が分かれていましたが、
今回から使いたい機能によってどの権限が必要かを考えなくてよくなりました。

ただし、アプリが使われていないタイミングでも位置情報の取得を行いたい場合は引き続きアプリは常に許可である必要があります。

## 感想
iOS13やべ〜〜〜〜〜〜

## 参考
[What's New in Core Location](https://developer.apple.com/videos/play/wwdc2019/705/)
WWDCの動画って日本語字幕で見れるんですね。めちゃくちゃ助かりました。
[CLLocationManager - Core Location | Apple Developer Documentation](https://developer.apple.com/documentation/corelocation/cllocationmanager?changes=latest_minor)