位置情報の取得
iOS14で位置情報を取得する
iOSアプリで位置情報を取得するときに配慮する点をまとめてみた①
Adding Location Services to Your App
デバイスが対応しているかを確認
位置情報サービス
をアプリで利用する場合は、アプリを使用するデバイスが対応しているか確認する必要がある。
メソッド | 概要 |
---|---|
significantLocationChangeMonitoringAvailable() | 位置情報が大きく変化した場合に、位置情報が更新できるかどうか |
isMonitoringAvailable(for:) | 現在地が位置情報を取得できる地点かどうか |
headingAvailable() | 進行方向を追跡できるかどうか |
isRangingAvailable() | iBeaconに対応しているかどうか |
位置情報サービスが利用できない場合のエラーハンドリング
また、デバイスで位置情報サービスが利用できない場合に送出されるエラーをハンドリングするため、
CLLocationManagerDelegate
で定義されたlocationManager(_:didFailWithError:)を実装するのが望ましい。
ユーザに位置情報サービスの認証を求める
Choosing the Location Services Authorization to Request
位置情報サービスの認証状態はアプリの使用中のみと常時の2つがあり、それぞれ以下のタイミングで位置情報サービスの利用が可能となる。
認証状態 | 利用可能タイミング |
---|---|
アプリの使用中のみ |
フォアグラウンドで実行中の場合 バックグラウンドで実行中 かつ 位置情報インジケータが有効である場合 |
常時 | - |
ただし、プライバシーや電力消費量などの点で、位置情報サービスの利用はなるべくアプリの使用中のみに限定するのが望ましい。
位置情報サービスの利用とイベントの受信
クラス・プロトコル | メソッド | 概要 |
---|---|---|
CLLocationManager | startUpdatingLocation() | 位置情報サービスの開始 |
CLLocationManagerDelegate | locationManagerDidChangeAuthorization(_:) | 位置情報サービスの認証状態が変化 |
CLLocationManagerDelegate | locationManager(_:didUpdateLocations:) | 位置情報が変化 |
CLLocationManagerDelegate | locationManager(_:didUpdateHeading:) | 進行方向が変化 |
CLLocationManager | requestLocation() | 現在地の取得 |
CLLocationManager | stopUpdatingLocation() | 位置情報サービスの終了 |
CLLocationManager
位置情報を扱うCore Location
サービスの開始と停止・設定を行う場合はCLLocationManagerを利用する。
CLLocationManager
は非同期で動作するTask
を実行するため、ローカル変数ではなく強参照のプロパティとしてアプリ内に保管しておく必要がある。
また、CLLocationManager
の初期化時にCLLocationManagerDelegate
で抽象的に定義されたlocationManagerDidChangeAuthorization(_:)メソッドを呼び出すため、
CLLocationManagerDelegate
プロトコルの実装クラスに対して、CLLocationManager
インスタンスのdelegate
プロパティをセットする必要がある。
class ViewController: UIViewController {
// CLLocationManagerは非同期処理を行うため、強参照のプロパティとしてアプリ内で保管させる
var locationManager: CLLocationManager?
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
// CLLocationManagerがCLLocationManagerDelegateプロトコルの抽象メソッドを実行するときは、
// CLLocationManagerDelegateプロトコルの実装クラスであるViewControllerに実行してもらう
locationManager!.delegate = self
// アプリの使用中のみ位置情報サービスの利用許可を求める
locationManager!.requestWhenInUseAuthorization()
}
}
// Delegateプロトコルの抽象メソッドを実装
// → ここで具体的な処理が実装される
extension ViewController: CLLocationManagerDelegate {
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
// 位置情報サービスの認証情報が変更された場合に実行する処理
}
}
位置情報の取得に関する設定
[iOS14]WWDC 2020 Core Location 新要素 Preciseについて
位置情報を正確にトラッキングする技術 in iOS — (第3回) バックグランドでのトラッキング、精度、バッテリー消費
CLLocationManager
のstartUpdatingLocation()やrequestLocation()で位置情報を取得する前に、
CLLocationManager
の位置情報の取得タイミングや取得精度などを定義する各プロパティに値をセットする。
プロパティ | 型 | 概要 |
---|---|---|
accuracyAuthorization | CLAccuracyAuthorization | ユーザの承認によって決まる位置情報の取得精度 |
pausesLocationUpdatesAutomatically | Bool | 位置情報が変化していない場合(※activityType を参照)に、位置情報の更新を一時停止するかどうか |
allowsBackgroundLocationUpdates | Bool | バックグラウンドでの位置情報の更新を行うかどうか |
showsBackgroundLocationIndicator | Bool | バックグラウンドで位置情報の取得を行っている場合に、インジケータを表示するかどうか |
activityType | CLActivityType | 位置情報が変化しているかどうかを識別するためのユーザのアクティビティ情報 |
distanceFilter | CLLocationDistance | 位置情報の取得間隔(距離) |
desiredAccuracy | CLLocationAccuracy | 位置情報の取得精度 |
headingFilter | CLLocationDegrees | 進行方向の取得間隔(角度) |
headingOrientation | CLDeviceOrientation | 進行方向を決定する際の画面の向き |
Delegateパターン
【Swift入門】難解なデリゲート(delegate)の使い方を理解しよう!
// Delegateプロトコル … 担当範囲のメソッドを抽象的に定義
protocol AttackDelegate {
// 攻撃するだけ(防御や回避は担当範囲外)
func attack()
}
// 依頼者 … 戦闘を行うが、どんな攻撃をするかは未定
class Fighter {
// 攻撃方法は後から自由に変更可能
var atkDelegate: AttackDelegate?
// 戦う
func fight() {
// 攻撃方法が決まっている場合は攻撃
if let delegate = self.delegate {
delegate.attack()
}
}
}
// 実行者 … 攻撃方法を決める(攻撃専門で、防御や回避は担当範囲外)
class Boxer: AttackDelegate {
// 攻撃方法を決める
func attack() {
print("パンチ")
}
}
// ↓↓↓
let fighter = Fighter() // Fighterをインスタンス化
let boxer = Boxer() // Boxerをインスタンス化
fighter.atkDelegate = boxer // 攻撃をBoxerに委譲
fighter.fight() // Boxerにパンチしてもらう