iOS8からの現在位置利用の際のアラート
iOS8からCoreLocationで位置情報を取得する方法が変わりました。
詳しくは以下を参照
iOS 8から位置情報を取得する方法が変わるよ
確認のアラートを出すとすぐ消える!
そこでサンプルコードを参考に実装したのですが、位置情報の取得の確認アラートを出した瞬間にアラートが消えてしまう問題が発生し、ハマりました。以下が問題のコードです。
sampleViewController.m
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
// 認証ステータスを確認し、必要なら認証リクエストを出す
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusNotDetermined) {
[locationManager requestAlwaysAuthorization];
}
else if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusAuthorizedAlways) {
[locationManager startUpdatingLocation];
}
// 緯度経度を取得
double lati = locationManager.location.coordinate.latitude;
double longi = locationManager.location.coordinate.longitude;
NSLog(@"Latitude = %f", lati);
NSLog(@"Longitude = %f", longi);
このコードで認証リクエストを出すと、確認アラートは出るのですが、ボタンをタップする間もなく消えます。
原因
原因は、CLLocationManagerをローカルで宣言していることでした。今回の実装では、現在位置の情報が手に入りさえすればもうCLLocationManagerは不要なので、プロパティで宣言する必要がないと判断し、ローカルで宣言したのですが、それが誤りでした。
CLLocationManagerを宣言しているメソッドがreturnすると、CLLocationManagerの変数がスタック領域から削除され、ヒープ領域からCLLocationManagerが解放されてしまいます。すると認証リクエストのアラートまで破棄されてしまったようです。
UIAlertControllerでは、ローカルで宣言して表示させてもアラートが消えることはありません。このイメージがあったため、今回ハマることになりました。
ですので、CLLocationManagerをローカルで宣言せず、プロパティ等でメソッドが終了しても解放されない位置で宣言する必要があります。念のため、修正後のコードをおいておきます。
sampleViewController.h
@property (strong, nonatomic) CLLocationManager *locationManager;
sampleViewController.m
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
// 認証ステータスを確認し、必要なら認証リクエストを出す
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusNotDetermined) {
[self.locationManager requestAlwaysAuthorization];
}
else if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusAuthorizedAlways) {
[self.locationManager startUpdatingLocation];
}
// 緯度経度を取得
double lati = self.locationManager.location.coordinate.latitude;
double longi = self.locationManager.location.coordinate.longitude;
NSLog(@"Latitude = %f", lati);
NSLog(@"Longitude = %f", longi);