※ 実装/動作確認環境: Xcode 11 beta7 + iOS 13 beta 8
TL; DR
- iOS13 & iOS12で位置情報を「常に許可」してもらう場合、Info.plistの値を以下のようにすることで適切に説明・誘導できそう
-
NSLocationWhenInUseUsageDescription
- XXXの利用には、「Appの使用中は許可」を選択してください。
-
NSLocationAlwaysAndWhenInUseUsageDescription
- XXXの利用には、「常に許可」を選択してください。
-
背景と概要
- iOS13からは
CLLocationManager.requestAlwaysAuthorization()
を実行しても、**「常に許可」**をすぐに取得できないようになり、アラートで2度許可を取得する必要がある - iOS12もサポートするアプリにおいて、位置情報を「常に許可」してもらうために、2つのアラート(および設定アプリ内)で表示される位置情報の用途について、どのように設定するのが妥当か調査・検討した
(おさらい)位置情報の用途の明示
位置情報を利用するためには、Info.plistに以下のKeyを設定し、用途を明示する必要がある
- NSLocationWhenInUseUsageDescription
-
NSLocationAlwaysAndWhenInUseUsageDescription
- 位置情報の利用を「常に許可」してもらう場合のみ必要
なお、以下の説明では、簡単のためNSLocationAlwaysAndWhenInUseUsageDescription
をAlways、NSLocationWhenInUseUsageDescription
をWhenInUseと表記する
表示される値の調査
何らかの方法で2度の確認アラートを回避する方法を模索した(ページ下部参照)が、結局は素直に2度のアラートでの許可取得に乗っかるしかなさそうと判断。
試してみたところ、呼び出すCLLocationManagerのメソッドやInfo.plistの定義内容によって、表示される値が異なるようなので、調査・整理した。
requestWhenInUseAuthorization()
の実行で表示される値
iOS12 & iOS13(共通)
表示箇所 | 表示される値 |
---|---|
許可取得アラート | WhenInUse |
設定アプリ内※1 | 下記参照 |
設定アプリ内で表示される値
Info.plistの定義内容に応じ、表示される値は異なる
- Info.plistに
WhenInUse
のみが定義されている場合
-
WhenInUse
の値が表示される
- Info.plistに
Always
とWhenInUse
の両方が定義されている場合
-
Always
の値が表示される- 位置情報の利用も「常に許可」が選択可能4
requestAlwaysAuthorization()
の実行で表示される値
iOS12
表示箇所 | 表示される値 |
---|---|
許可取得アラート | Always |
設定アプリ内※1 | Always |
iOS13
表示箇所 | 表示される値 |
---|---|
許可取得アラート(1回目)※2 | WhenInUse |
許可取得アラート(2回目)※3 | Always |
設定アプリ内※1 | Always |
- ※1: 設定 > アプリ名 > 位置情報 のフッターに表示されるもの
- ※2: {Appの使用中は許可, 1度だけ許可, 許可しない}の3つの選択肢があるアラート
- ※3: {"使用中のみ許可"のままにする, "常に許可"に変更}の2つの選択肢があるアラート
iOS13 & iOS12で「常に許可」に誘導するための文言設計
上記の調査内容に基づき、以下のような内容にする予定
-
WhenInUse
- XXXの利用には、「Appの使用中は許可」を選択してください。
-
AlWays
- XXXの利用には、「常に許可」を選択してください。
このようにしたときの挙動
※requestAlwaysAuthorization()
のみ利用する想定
- iOS12
-
requestAlwaysAuthorization()
のアラートで"「常に許可」を選択…"(=Alwaysの内容)が表示される
-
- iOS13
-
requestAlwaysAuthorization()
のアラートで"「Appの使用中は許可」を選択…"(=WhenInUseの内容)が表示される - のちに表示されるアラートで"「常に許可」を選択…"(=Alwaysの内容)が表示される
-
(参考)設定アプリ内の許可状態と取得できるステータスの対応
当初は「常に許可」でなければ設定アプリに誘導する手を検討した。
しかし、WWDC発表内容1等にもある通り、詳細なステータス(WWDC資料ではTemporary
やProvisional
と示されているもの)はラップされており、かつ調べてみると想像以上に扱いづらそうなので断念した。
設定アプリ内で参照できる許可状態とアプリ上で取得できる許可ステータスの対応を確認した結果は以下の通り。
設定アプリ内の許可状態※1※2 | 取得できるステータス※3 |
---|---|
(許可取得前) | notDetermined |
なし | denied |
次回確認(起動中に位置情報の許可取得を行っていない) | notDetermined |
次回確認(起動中に「1回だけ許可」を選択) | authorizedWhenInUse |
このAppの使用中のみ許可 | authorizedAlways |
常に | authorizedAlways |
- ※1 表内の文言はiOS13のもの(iOS12とは若干異なる)
- ※2 ()内の値は本表作成にあたり付記した注釈
- ※3
CLLocationManager.authorizationStatus()
の値
authorizedAlways
のステータスが「このAppの…」と「常に」に対応するのは、発表内容の通りであり、またプライバシー保護の旗印のもとであればやむなしといった印象。
が、次回確認(起動中に位置情報の許可取得を行っていない)
と 次回確認(起動中に「1回だけ許可」を選択)
の状態があり、それぞれ対応するステータスとの入り組み具合を見ると、(自分で書いたものながら)「お前は何を言っているんだ」感がすごい。
-
iOS 13ではCLLocationManagerでrequestAlwaysAuthorizationを呼んでも常に許可という選択肢はでない ↩
-
どの方法で許可を取得しようとしたかではなく、
NSLocationAlwaysAndWhenInUseUsageDescription
の有無で決まる模様。ドキュメントにも、「この値は位置情報へのアクセスを常に行う際に必要」と口酸っぱく念押しのように書かれている。 ↩