iOS8 x iBeacon x swift (XCode6)ではまった

sfiftでiBeaconサンプルでも作ってみるかとやってみたら変なところで嵌ってしまったので
メモ程度に残しておきます。

問題

Info.plistに正しく設定しても、iOSの位置情報利用確認のアラートがでない。
こんなやつ。

f:id:rochefort:20150110160639j:plain

解決方法

先に解決方法書いておくと、 プロジェクトのInfoタブにtarget毎のinfo.plistの設定が見れるのですが
どういうわけかここに反映されない。
なのでinfo.plistに追加したけどダメな場合はここにも追加するとうまく動きました。
これXCode6のバグなんじゃなかろうか。
(追加するkeyについては後述)
 

Info.plist

f:id:rochefort:20150110160719p:plain

target 設定

f:id:rochefort:20150110160829j:plain

位置情報サービスのおさらい

このあたりはググればたくさん出てきますが、一応おさらい。

iOS8 からは 位置情報利用の選択肢が増えました。 これによって、info.plist に設定するキー名も変更され、CLLocationManagerにそれぞれ許可を促すメソッドも追加されています。

選択肢 key名 メソッド
WhenInUse(使用中のみ許可) NSLocationWhenInUseDescription requestWhenInUseAuthorization
Always(常に許可) NSLocationAlwaysUsageDescription requestAlwaysAuthorization

どっちを利用するか

こちらに表及び詳細が記載されています。
iOS 8 の位置情報のプライバシー設定に対応する – I'm Sei.

両方書いてもいいんですが、今回はバックグラウンドでMonitoringしたいのでAlwaysで作成することにします。

ソースざっくり

まずは、CoreLocation.framework を追加してimportして
位置情報でお馴染みのCLLocationManager をインスタンス化します。

import CoreLocation


private let locationManager = CLLocationManager()

CLLocationManagerDelegate を追加して、利用箇所でdelegateを設定すれば

self.locationManager.delegate = self;

locationManager:didChangeAuthorizationStatus: が呼ばれるので、statusに応じて 利用確認するか、Monitoring開始するかを書けばok。(Monitoringのところは省略)

    func locationManager(manager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
        switch status {
        case .NotDetermined:
            self.locationManager.requestAlwaysAuthorization();
        case .Restricted:
            println("Error: It is restricted by settings.")
        case .Denied:
            println("Error: It is denied Location Service.")
        case .Authorized:
            self.locationManager.startMonitoringForRegion(self.beaconRegion)
        default:
            break
        }
    }

See Also:

iBeaconハンドブック 読了 - rochefort's blog