【iOS 9対応】知っておきたい位置情報周りの変更点

<i>※本記事は、[一般に公開されている情報](http://devstreaming.apple.com/videos/wwdc/2015/714tqy593v/714/714_whats_new_in_core_location.pdf?dl=1)を元に作成しています。記事中の画像はWWDCのスライドのものを引用させて頂いております</i>

位置情報を扱うiOSアプリを開発する際に必要となる <b>Core Location</b> ですが、iOS 9でもいくつか変更点があるようです。以下に変更点をまとめます。

# Background Location

iOS 8までは「Capabilities > Background Modes > Location updates」にチェックを入れておくだけでバックグラウンドでも継続的に位置情報を取得することができました。

![スクリーンショット 2015-07-01 18.48.49.png](https://qiita-image-store.s3.amazonaws.com/0/8292/415b4d19-6da0-78f3-6814-d54dd399a4ae.png "スクリーンショット 2015-07-01 18.48.49.png")

iOS 9からは `CLLocationManager` に

```swift
var allowsBackgroundLocationUpdates: Bool
```

というプロパティが追加され、これを `true` にしないと<B>バックグラウンドで位置情報を取得できない</B>ようです。

注意しないといけないのが、このプロパティは<B>デフォルトで `false` </B>だということです。iOS 9以上で、かつバックグラウンドでの位置情報取得が必要な場合は、このプロパティを `true` にする必要がありそうです。

```swift
let locationManager = CLLocationManager()
if #available(iOS 9.0, *) {
    locationManager.allowsBackgroundLocationUpdates = true
}
```


# Single location

iOS 8までは、`startUpdatingLocation` メソッドを用いて継続的に位置情報を取得し続けることができました。一方、一回だけ位置情報を取得したい場合には、フラグなどを用意して自前で処理を実装する必要がありました。

iOS 9からは

```swift
func requestLocation()
```

というメソッドが追加になっており、<b>一度きりの位置情報取得が可能になりました。</b>

このメソッドを実行すると、指定された測位精度（desiredAccuracy）に基づき測定を行い、位置情報が取得できた際には

```swift
-locationManager:didUpdateLocations:
```

が呼ばれ、取得できなかった場合は

```swift
-locationManager:didFailWithError:
```

が呼ばれます。

# Authorization

ユーザーに位置情報の使用許可を求める際、

```objc
-requestWhenInUseAuthorization
-requestAlwaysAuthorization
```

のメソッドを使う点はiOS 8から変わっていません。

（参考）[iOS 8から位置情報を取得する方法が変わるよ](http://qiita.com/koogawa/items/6ec24ca3201977e9642b)

iPhone側で許可を求める際のフローもこれまでと変わっていません。

一方、Apple Watchにおいては、Watch Extensionが実機側に移動したこともあり、この辺の挙動が変わっています。

それぞれ詳しく見て行きましょう。

# iPhone側で許可する場合

![スクリーンショット 2015-07-02 15.45.17.png](https://qiita-image-store.s3.amazonaws.com/0/8292/b33dbea3-f2d3-c82c-bf81-08b7fb30d858.png "スクリーンショット 2015-07-02 15.45.17.png")

これまで通り、iPhone上に許可を求めるアラートが表示されます。Apple Watch上には何も表示されません。

# Apple Watch上で許可する場合

![スクリーンショット 2015-07-02 15.33.29.png](https://qiita-image-store.s3.amazonaws.com/0/8292/585eeda2-1200-9461-f00b-f0a7384c9fdd.png "スクリーンショット 2015-07-02 15.33.29.png")

iPhoneアプリ側で位置情報の使用を許可するよりも先にWatchアプリ側で位置情報を使おうとした場合がこのパターンです。フローは次の通りです。

1. Apple Watch上に「iPhone側で位置情報の使用を許可するよう求めるアラート」が表示される（dismissボタンで閉じれる）
2. iPhone上に許可を求めるアラートが表示される
3. iPhone上で許可するとApple Watchでも位置情報が取得できるようになる

このようなフローになっているのは、ユーザにApple Watch上で位置情報の使用を許可させるのはあまり良いUXではない、ことなどが理由のようです。詳しくはWWDCのビデオを参照してください。


https://developer.apple.com/videos/wwdc/2015/?id=714



# Apple Watch: Best practice

watchOS 1までは、位置情報を取得する際に

```swift
-startUpdatingLocation
```

メソッドが使用できました。

しかし、watchOS 2からはこのメソッドが<b>使えなくなっています</b>（deprecatedではなく使用不可）。

代わりに、先ほど紹介した `requestLocation` メソッドを使うようです。つまり、基本的にwatchOS 2では継続的な位置情報の取得ができません。

どうしても継続的に位置情報を取りたい場合は <b>Watch Connectivity</b> を使ってね、ということらしいです。Watch Connectivityについては、次のビデオを参照してください。

* https://developer.apple.com/videos/wwdc/2015/?id=713

また、私の記事でも詳しく解説しています。

* http://qiita.com/koogawa/items/b39e1419cbbcda8efc07

ここでは、Watch Connectivityを用いて継続的に位置情報を取得する際に使用するメソッド名のみ載せておきます。

## Watch -> iPhone

```
-sendMessage:replyHandler:errorHandler:
```

## iPhone -> Watch

```
-updateApplicationContext:
-allowDeferredLocationUpdatesUntilTraveled:timeout:
```

# 参考になるリンク

* [What's New in Core Location](https://developer.apple.com/videos/wwdc/2015/?id=714) - WWDC 2015のビデオ（[PDF](http://devstreaming.apple.com/videos/wwdc/2015/714tqy593v/714/714_whats_new_in_core_location.pdf?dl=1)）
* [PotLoc: CoreLocation with iPhone and Apple Watch](https://developer.apple.com/library/prerelease/watchos/samplecode/PotLoc/Introduction/Intro.html) - watchOS 2で位置情報を取得するサンプルコード

----

<i>本記事は http://blog.koogawa.com/entry/2015/07/02/165656 でも公開しております。</i>