iPhone 経緯度から地名を取得する方法を実装してみた

今日は位置情報から地図情報(住所とか)を取得する方法を学んだので記載したいと思います。

地図情報を取得するとは

位置情報(経緯度)の取得は、CLLocationManagerを使って実現できます。でもその情報ってユーザーからすると分かりづらい。経緯度を地名に変換する事でユーザーフレンドリーな情報に変換する。それが地図情報の取得です。下の図は地図情報を取得した例(浦安駅近くのミスドの場所)です。国名、都道府県、市町村、丁番号まで取得できるようです。


前準備

地図情報を取得するために以下の準備が必要です。ヘッダファイルの実装例を示します。
1、Mapkit.frameworkをアプリケーションに追加する。
2、ヘッダファイルにMapkit.frameworkをインポートする。
3、位置情報取得時に利用するデリゲート「MKReverseGeocoderDelegate」をクラスに設定する。

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
@interface GeocodingViewController : UIViewController 
<CLLocationManagerDelegate, MKReverseGeocoderDelegate> {

CLLocationManager *locationManager;
UILabel *showLabel;
}

@property (nonatomic, retain) IBOutlet UILabel *showLabel;
- (IBAction) start : (id)sender;

@end

地図情報取得を開始する

地図情報を取得するには以下のようなコードを記載します。

- (void)locationManager:(CLLocationManager *)manager 
didUpdateToLocation:(CLLocation *)newLocation 
  fromLocation:(CLLocation *)oldLocation {
NSTimeInterval howRecent = [newLocation.timestamptimeIntervalSinceNow];
if (abs(howRecent) < 15.0) {
 // stop locationManager  
  [locationManager stopUpdatingLocation];
  // start Geocoder
  MKReverseGeocoder *geoCoder = [[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate];
  geoCoder.delegate = self;
[geoCoder start];
} else {
  NSLog(@"skip");
}
}

ここではCLLocationManagerを利用して位置情報を取得した後、それを利用して地図情報取得を開始しています。CLLocationManagerを利用した位置情報取得方法はこちらを参考にしてみて下さい。
地図情報取得を開始するためには、CLLocationオブジェクトを利用してMKReverseGeocoderインスタンスを作成後、デリゲートの設定、開始処理の呼び出しを実行します。


位置情報を取得する

位置情報が取得できたら、MKReverseGeocoderのデリゲートに設定したMKReverseGeocoderDelegateプロトコルのメソッドが呼び出されます。コード例は以下です。

- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark {
NSMutableString *str = [[NSMutableString alloc] init];
[str appendFormat:@"longitude : %f \n", placemark.coordinate.longitude];
[str appendFormat:@"latitude : %f \n", placemark.coordinate.latitude];
[str appendFormat:@"country : %@ \n", placemark.country];
[str appendFormat:@"state : %@ \n", placemark.administrativeArea];
[str appendFormat:@"addtional state : %@ \n", placemark.subAdministrativeArea];
[str appendFormat:@"locality : %@ \n", placemark.locality];
[str appendFormat:@"additional locality : %@ \n", placemark.subLocality];
[str appendFormat:@"street : %@ \n", placemark.thoroughfare];
[str appendFormat:@"additional street : %@ \n", placemark.subThoroughfare];
[str appendFormat:@"postcode : %@ \n", placemark.postalCode];
showLabel.text = str;
}

ここでは、地図情報を保持するMKPlacemarkオブジェクトから色々と情報を取得しています。MKPlacemarkオブジェクトから、国名、都道府県名、市町村名、丁番号など色々な値が取得できます。上記で取得している意外にもプロパティを保持しています。詳細はMKPlacemark Class Referenceを参考にしてください。

なお、エラーが発生した場合には、以下のメソッドを実装しておけばエラーハンドリングが可能です。エラーハンドリングの例は以下です。

- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error {
    NSLog(@"MKReverseGeocoder has failed. %@, %@", error, [error userInfo]);
}

まあここではログを出すだけですが。。エラー情報を出力しています。


地図情報に関するいろいろ

■ iOSでは現在、経緯度→地図情報の取得は上記のように出来ますが、地図情報→経緯度は出来ません。やりたい場合にはサードパーティ製品を利用する必要があります。
■ 地図情報取得はネットワークを利用するため、ネットワーク接続は必須です。ネットワーク接続されていない場合、エラーが発生します。
■ 一度に取得できる地図情報は最大1つ。
■ その他Geocodingについて詳細を調べたい場合にはThe Google Geocoding APIを参考に。


最後に

地名を取得することも簡単にできる事に驚きです。Mapを利用したアプリケーションを作成するときに重宝しそうです。次こそはMapアプリを作ってみよっと。
ついでに、私のTwitter@yoheiMune)も宜しくお願いします。