What's new in location
要点
iOS14以降は、
・位置情報精度について、full
、reduced
の2パターンが追加され、どちらの値だったとしてもアプリ側が対応できるようにしておく必要がある。
・full
精度ではないとできないような機能がある場合、「一時的なfull
精度の許可」を求めるか、「設定アプリにユーザーを飛ばして設定を変更してもらう」という対応のどちらかにすると良い。
・必要もないのにfull
精度の許可をユーザーに求めるような事は適切でない。reduced
精度をデフォルト設定とする事もできるので、選択肢の一つとして考えるべき。
詳細
iOS13以降では、位置情報取得の可否についてユーザーは許諾ダイアログまたは設定アプリから3通りの選択肢を選ぶことができた。
- Never(取得不可)/ While Using(アプリ使用中のみ取得可)/ Always(常に取得可)
※ Always(常に取得可)は最初の許諾ダイアログでいきなり選択することができるわけではなく、「Once(一回許可)」を押した後、少し時間が経ってから常に取得可能に変更するかどうか尋ねるダイアログが出現する形式であった。
→ アプリの種類によっては、非常に正確な位置情報がいるもの(地図アプリなど)と、位置情報の精度はユーザーの好みに任せていいもの(SNS、マッチングアプリなど)がある。つまり取得する情報の精度をコントロールできた方がいい。そのため、iOS14以降から、**Precise(精度)**という項目が位置情報許諾ダイアログ並びに設定アプリに追加され、正確な位置情報まで送るかどうかを選べるようになった。(**Full(正確な位置情報)**か、**Reduced(大まかな位置情報)**の二択)
※見ればわかるように、精度のほかユーザーがいる地点周辺の地図も一緒に表示されるようになった。
これに合わせて、CLLocationManager
クラスのauthorizationStatusメソッドは廃止予定になり、以下の列挙形で位置情報精度を表すようにする。
var accuracyAuthorization: CLAccuracyAuthorization { get }
enum CLLAccuracyAuthorization {
case fullAccuracy
// 正確な精度で位置情報を提供する事をユーザーが許可した場合。iOS13以前はこれしかなかったのと同じ状態。
case reducedAccuracy
// 大まかな精度でのみ位置情報を提供する事をユーザーが許可した場合。
}
またCLAuthorizationStatus
かCLAccuracyAuthorization
のどちらか一方でも変更があった場合、以下の新規追加されたデリゲートメソッドが呼ばれるようになった。
locationManager(_:didChangeAuthorization:) //deprecated
locationManagerDidChangeAuthorization(_:) //新規追加(iOS14以降)
//使用例
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
switch manager.authorizationStatus {
case .authorizedAlways, .authorizedWhenInUse:
//フラグON
self.hasSomePermission = true
case .notDetermined, .denied, .restricted:
//フラグOFF
self.hasSomePermission = false
default:
print("Unhandled case")
}
switch manager.accuracyAuthorization {
case .reducedAccuracy:
self.gettingExactLocation = false
case .fullAccuracy:
self.gettingExactLocation = true
default:
print("This should not happen!")
}
}
-> 従来位置情報を使用していたアプリについて、accuracyAuthorization
がどちらの値になっても対応できるようにする必要がある。
-
位置情報は従来通り、
locationManager:didUpdateLocations:
メソッドでCLLocation
クラスオブジェクトとして渡されてくる。これは1時間に4回ほどアップデートされるのだが、精度がfullAccuracy
の場合、ユーザーのいる代表的な座標と考えるのではなく、ユーザーが本当にその時点でいる座標として取り扱うこと。 -
AppleのMapアプリも
reducedAccuracy
をサポートする形でアップデートされる。具体的には、ユーザーの位置は青い点ではなく、大まかな位置を示す円で表されることになる。 -
full
の精度が必要なのに、reduced
の精度の取得許可しかユーザーから得られていない場合どうするか。- 設定アプリへ飛ばし、設定を変更するようユーザーに促す。ただユーザーにとって面倒な動作なので、あまりやりたくはない。
- 新しいメソッドの
requestTemporaryFullAccuracyAuthorization(withPurposeKey:completion:)
を使い、一時的にfull
精度の位置情報取得を行う許可を得ることが可能。この後は、位置情報そのものの許可ダイアログで「Once(一回許可)」を押した時と似た振る舞いとなり、次にアプリを起動した際、full
精度の位置情報取得を恒久的に許可するかのダイアログがユーザーに表示されることとなる。
@IBAction func userWantsToNavigate(_ sender: Any) {
//`reduced`の精度の取得許可しかユーザーから得られていない
if manager.accuracyAuthorization = .reducedAccuracy {
//一時的な許可をユーザーに求める
//puroposeKeyとは、InfoPlistの NSLocationTemporaryUsageDescriptionDictionaryの中にあらかじめ記載した、キー文字列。
manager.requestTemporaryFullAccuracyAuthorization(withPurposeKey: "WantsToNavigate") {
//許可が得られた場合
if self.manager.accuracyAuthorization = .fullAccuracy {
self.beginNavigation()
}
}
} else {
self.beginNavigation()
}
}
<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dict>
<key>WantsToNavigate</key>
<string>歩行ルートを計算するために正確な位置情報が必要です。</string>
<key>HogeHoge</key>
<string>HogeHogeするために正確な位置情報が必要です。</string>
</dict>
-
方針
- 精度が
reduced
の場合、AppleのMapアプリのように、それをUIに反映させることが推奨される。例えば、精度がreduced
の場合はユーザーの大まかな位置を円で表す・現在の精度が何かをラベルで表示するなど。これにより、reduced
でもアプリが対応できるようにし、必要もないのに常にfull
精度を要求する事は止める。 - 精度が
full
でないと使えない機能がある場合(Mapアプリでいうルート検索機能など)は、上で書いたように一時許可を求めても問題ない。Mapアプリは、このような一時許可を求める形式を取っている。
- 精度が
精度がreduced
が適用され、低い精度にしても多くの距離を移動したと判定できる場合のみ通知される。同じ場所に止まっていると判定できる場合は、従来通り通知しない。
やはり精度reduced
が適用される。通知されるタイミングについてはfull
でも変わらないが、通知される場所が大まかなものになる(例えば、full
なら「◯○公園に到着」と通知される所、rduced
では「××市に到着」となる等)。
精度reduced
では使用できない = 常にfull
精度の位置情報が必要。
例として、Apple公式のReminder
アプリでは、特定のエリアを起点にしてリマインドを行う機能がある。これはRegion Monitoring
により行われている。
Reminder
アプリのこの機能では、常にfull
精度の位置情報を要求し、reduced
精度では意味をなす動作ができない。このことから、上に述べたMap
アプリのような、一時的にfull
精度を求めるような事はせず、端的にユーザーに設定アプリに飛んでfull
精度を許可するよう促す形式を取っている。
このように、設定アプリに飛んで設定変更を促すという動作を自作アプリでしたい時は、果たして適切かどうかを考える必要がある。
-
full
精度の許可が得られているものの、実際にはreduced
精度しか必要がない場合- このような場合は、
LocationManager
クラスのdesiredAccuracy
に、kCLLocationAccuracyReduced
というiOS14からの新しい値をセットする。
- このような場合は、
var locationManager = CLLocationManager()
locationManager.desiredAccuracy = kCLLocationAccuracyReduced
- そもそも
reduced
精度しか許可を求めない場合
<key>NSLocationDefaultAccuracyReduced</key>
<true/>
Info.plist
に上記のように記載すると、Reduced
精度のみ許可を求めるようになる(精度を選ぶボタンが表示されなくなる)。
ただ、この設定をしてもSettings
アプリからfull
精度を選択する事はなお可能となっている。
Apple公式の TV
アプリでは、視聴できる番組を制限するためユーザーの地域を知る必要があり、位置情報を取得している。ただどの国にいるかなど大まかな位置だけ知れれば良いために、この機能を利用している。
-
reduced
精度の裏側の実装
reduced
精度は、「ユーザーの本当の位置の周りにノイズを付加する」というような方法で算出されるのではない。地面をあるエリアごとに分け、1時間におよそ4回ほど、ユーザーがどのエリアにいるかを計測して行っている。1エリアの大きさは都市地域では数キロごとだが、人口がまばらな地域では10キロを超えることがある。このように大まかなエリアごとの区分けでしかないため、実際にいる市の隣の市にいると判定されることもありうる。
- Watch Appとの連携
Apple Watchのコンパニオンアプリ内で制度に関する許可をした場合、これと連動するiPhoneアプリでも自動的に許可が適用される。
参考