iOS Developer Libraryの「位置情報対応プログラミングガイド」(英語版はMaking Your Application Location-Aware)に沿って、サンプルを公開します。
注意点
ジオコーディングは、サーバにリクエストを送り、サーバ側で処理をするものです。そのため、過度にジオコーディング要求をしてはいけません。詳細は「位置情報対応プログラミングガイド」23ページ目「Geocoderオブジェクトについて」をご覧ください。また、MapKitを利用した逆ジオコーディングは、Googleマップの利用規約により、必ずGoogleマップと組み合わせなければなりません。他の会社の地図サービスなどに出力したりすることはできません。(Googleマップの利用規約(section 10.12))
詳細は、Googleマップの利用規約(Google Maps Terms of Service)(全文)をご覧ください。
正ジオコーディングと逆ジオコーディング
逆ジオコーディングはiOS 3.0以降ですが、正ジオコーディングはiOS 5.0以降でなければ使えません。概要 | フレームワーク | |
---|---|---|
正ジオコーディング | 「住所」→「緯度・経度」 | CoreLocation【iOS 5.0以降】 |
逆ジオコーディング | 「緯度・経度」→「住所」 | MapKit【iOS 3.0以降】【Deprecated in iOS 5.0】 CoreLocation【iOS 5.0以降】 |
実装手順
正ジオコーディング(CoreLocation)
- 「CoreLocation.framework」の追加
- ヘッダのインポート
#import <CoreLocation/CoreLocation.h>
- 正・逆ジオコーディングの開始
// インスタンスの生成 CLGeocoder *geocoder = [[[CLGeocoder alloc] init] autorelease]; // 正ジオコーディングの開始 [geocoder geocodeAddressString:@"住所".text completionHandler:^(NSArray *placemarks, NSError *error) { if (error) { // エラーが発生している } else { for (CLPlacemark *p in placemarks) { // 複数の結果が存在する場合もある } } }]; // 逆ジオコーディングの開始 CLLocation *location = [[[CLLocation alloc] initWithLatitude:37.332708 longitude:-122.030336] autorelease]; [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) { if (error) { // エラーが発生している } else { if (0 < [placemarks count]) { // 結果はひとつしかない } } }];
MapKit.framework
- 「MapKit.framework」の追加
- ヘッダのインポート
#import <MapKit/MapKit.h>
- MKReverseGeocoderDelegateプロトコルの宣言
@interface ViewController : UIViewController <MKReverseGeocoderDelegate> @property (nonatomic, retain) MKReverseGeocoder *geocoder; @end
- 逆ジオコーディングの開始
ガイドラインに書かれている以下のような方法だと、MKReverseGeocoderオブジェクトが解放されずにiOS 5.0以降ではメモリリークします。(Xcode付属のサンプル「CurrentAddress」では正しく書かれています。)@synthesize geocoder = _geocoder; - (void)reverseGeocode:(CLLocationCoordinate2D)coord { self.geocoder = [[[MKReverseGeocoder alloc] initWithCoordinate:coord] autorelease]; _geocoder.delegate = self; [_geocoder start]; }
- (void)reverseGeocode:(CLLocationCoordinate2D)coord { // theGeocoderは解放されない MKReverseGeocoder *theGeocoder = [[MKReverseGeocoder alloc] initWithCoordinate:coord]; theGeocoder.delegate = self; [theGeocoder start]; }
- 逆ジオコーディングの受け取り
/* エラー発生時 */ - (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error { // ここで任意の処理 NSLog(@"%s | %@", __PRETTY_FUNCTION__, error); } /* ジオコーディング成功時 */ - (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark { // ここで任意の処理 }
ジオコーディングの実行例
デバイスの言語の設定により、得られる情報が異なります。また、正ジオコーディング結果の緯度・経度も、regionも値が返ってくるわけでもないようです。CoreLocationでの正ジオコーディングの例
住所 | 緯度, 経度 |
---|---|
東京タワー | +35.658608, +139.745396 |
Apple Inc. 2 Infinite Loop | +37.332708, -122.030336 |
MapKitでの逆ジオコーディング「東京タワー」の例(iOS 5.1)
プロパティ | 日本語環境 | 英語環境 |
---|---|---|
addressDictionary | { City = "港区"; Country = "日本"; CountryCode = JP; FormattedAddressLines = ( "日本", "東京都港区4丁目2−8" ); State = "東京都"; Street = "4丁目 2−8"; SubLocality = "芝公園"; SubThoroughfare = "2−8"; Thoroughfare = "4丁目"; } | { City = Minato; Country = Japan; CountryCode = JP; FormattedAddressLines = ( Japan, "Tokyo, Minato, Shibakoen, 4丁目2−8" ); State = Tokyo; Street = "4丁目 2−8"; SubLocality = Shibakoen; SubThoroughfare = "2−8"; Thoroughfare = "4丁目"; } |
administrativeArea | 東京都 | Tokyo |
areasOfInterest | (null) | (null) |
country | 日本 | Japan |
inlandWater | (null) | (null) |
locality | 港区 | Minato |
name | (null) | (null) |
ocean | (null) | (null) |
postalCode | (null) | (null) |
region | (null) | (null) |
subAdministrativeArea | (null) | (null) |
subLocality | 芝公園 | Shibakoen |
subThoroughfare | 2−8 | 2−8 |
thoroughfare | 4丁目 | 4丁目 |
MapKitでの逆ジオコーディング「Apple Inc.」の例(iOS 5.1)
プロパティ | 日本語環境 | 英語環境 |
---|---|---|
addressDictionary | { City = "クパチーノ"; Country = "アメリカ合衆国"; CountryCode = US; FormattedAddressLines = ( "2 インフィニート・ループ", "クパチーノ カリフォルニア 95014", "アメリカ合衆国" ); State = "カリフォルニア"; Street = "2 インフィニート・ループ"; SubThoroughfare = 2; Thoroughfare = "インフィニート・ループ"; ZIP = 95014; } | { City = Cupertino; Country = "United States"; CountryCode = US; FormattedAddressLines = ( "2 Infinite Loop", "Cupertino, CA 95014", USA ); State = California; Street = "2 Infinite Loop"; SubThoroughfare = 2; Thoroughfare = "Infinite Loop"; ZIP = 95014; } |
administrativeArea | カリフォルニア | California |
areasOfInterest | (null) | (null) |
country | アメリカ合衆国 | United States |
inlandWater | (null) | (null) |
locality | クパチーノ | Cupertino |
name | (null) | (null) |
ocean | (null) | (null) |
postalCode | 95014 | 95014 |
region | (null) | (null) |
subAdministrativeArea | (null) | (null) |
subLocality | (null) | (null) |
subThoroughfare | 2 | 2 |
thoroughfare | インフィニート・ループ | Infinite Loop |
CoreLocationでの逆ジオコーディング「東京タワー」の例(iOS 5.1)
プロパティ | 日本語環境 | 英語環境 |
---|---|---|
addressDictionary | { City = "東京"; Country = "日本"; CountryCode = JP; FormattedAddressLines = ( "東京タワー", "〒105-0011", "東京 港区", "芝公園 4丁目2番", "日本" ); Name = "東京タワー"; State = "東京"; Street = "芝公園 4丁目2番"; SubLocality = "芝公園"; SubThoroughfare = "2番"; Thoroughfare = "芝公園 4丁目2番"; ZIP = "〒105-0011"; } | { City = Minato; Country = Japan; CountryCode = JP; FormattedAddressLines = ( "Tokyo Tower", "〒105-0011", "Tokyo Minato", "2, Shibakoen 4-Chōme", Japan ); Name = "Tokyo Tower"; State = Tokyo; Street = "2, Shibakoen 4-Chōme"; SubLocality = Shibakoen; SubThoroughfare = 2; Thoroughfare = "Shibakoen 4-Chōme"; ZIP = "〒105-0011"; } |
administrativeArea | 東京 | Tokyo |
areasOfInterest | ("東京タワー") | ("Tokyo Tower") |
country | 日本 | Japan |
inlandWater | (null) | (null) |
locality | 港区 | Minato |
name | 東京タワー | Tokyo Tower |
ocean | (null) | (null) |
postalCode | 〒105-0011 | 〒105-0011 |
region | (identifier <+35.65860800,+139.74534650> radius 133.46) <+35.65860800,+139.74534650> radius 133.46m | (identifier <+35.65860800,+139.74534650> radius 133.46) <+35.65860800,+139.74534650> radius 133.46m |
subAdministrativeArea | (null) | (null) |
subLocality | 芝公園 | Shibakoen |
subThoroughfare | 2番 | 2 |
thoroughfare | 芝公園 4丁目 | Shibakoen 4-Chōme |
CoreLocationでの逆ジオコーディング「Apple Inc.」の例(iOS 5.1)
プロパティ | 日本語環境 | 英語環境 |
---|---|---|
addressDictionary | { City = "クパチーノ"; Country = "合衆国"; CountryCode = US; FormattedAddressLines = ( "Apple Inc.", "2 Infinite Loop", "Cupertino, CA 95014-2083", "合衆国" ); Name = "Apple Inc."; PostCodeExtension = 2083; State = "カリフォルニア"; Street = "2 Infinite Loop"; SubAdministrativeArea = "サンタクララ"; SubLocality = "Bay Area"; SubThoroughfare = 2; Thoroughfare = "Infinite Loop"; ZIP = 95014; } | { City = Cupertino; Country = "United States"; CountryCode = US; FormattedAddressLines = ( "Apple Inc.", "2 Infinite Loop", "Cupertino, CA 95014-2083", "United States" ); Name = "Apple Inc."; PostCodeExtension = 2083; State = California; Street = "2 Infinite Loop"; SubAdministrativeArea = "Santa Clara"; SubLocality = "Bay Area"; SubThoroughfare = 2; Thoroughfare = "Infinite Loop"; ZIP = 95014; } |
administrativeArea | カリフォルニア | California |
areasOfInterest | ("Apple Inc.") | ("Apple Inc.") |
country | 合衆国 | United States |
inlandWater | (null) | (null) |
locality | クパチーノ | Cupertino |
name | Apple Inc. | Apple Inc. |
ocean | (null) | (null) |
postalCode | 95014 | 95014 |
region | (identifier <+37.33100000,-122.03085000> radius 414.66) <+37.33100000,-122.03085000> radius 414.66m | (identifier <+37.33100000,-122.03085000> radius 414.66) <+37.33100000,-122.03085000> radius 414.66m |
subAdministrativeArea | サンタクララ | Santa Clara |
subLocality | Bay Area | Bay Area |
subThoroughfare | 2 | 2 |
thoroughfare | Infinite Loop | Infinite Loop |
サンプル
ソースコードはGitHubにて公開しています。- CoreLocationを利用
- MapKitを利用
CoreLocationを利用したサンプル
MapKitを利用したサンプル
今回はサンプルでUITableViewやUIMapViewを利用していますが、残念ながらiOS 5.1ではUIScrollViewが内部でメモリリークしています。
フォーラムでも報告されており「Developer Forums: iOS 5.1 libsystem_c.dylib leaks memory when UIScrollview scrolling hits a bound」、日本語の説明ですと「iOS 5.1 ではスクロールビューをスクロールするたびに少しずつメモリリークが起こる。 - 24/7 twenty-four seven」にも書かれております。
そのため、UIScrollViewを継承しているUITableViewやUIMapViewでも同様にメモリリークしてしまいます。
0 コメント:
コメントを投稿