はじめに
iPhone・

今回は、
- 地図の移動
- 逆ジオコーディング
(経緯度から住所の取得) - 地図の種類の変更
- マーカーの表示
少しアプリらしくということで、
ツールバーの追加
最初にアプリの画面を作ります。プロジェクトは前回の内容を参考に、
今回はツールバーを追加します。プロジェクト名+ViewContoller.


ツールバーのボタンも追加します。ツールバー上にBar Button Itemをドラッグ&ドロップします

InspectorパレットのAttributesタブをクリックして、

それぞれのボタンは次の機能を割り当てます。
- Me: 現在地の表示
- RevGeo: 逆ジオコーディング
- Mode: 地図の種類の変更
- Pin: マーカーの表示
- Share: メールの送信
コードの編集
ボタンをタップしたとき各種処理ができるよう準備しておきましょう。ボタンのタップなどのイベントは、
Xcodeウィンドウ右上のほうにあるEditorの中央ボタンをクリックすると、

すると図7のように名前を入力するダイアログが表示されます。ここにアクションの名前を入力してConnectボタンをクリックします。

以上で、
- (IBAction)meAction:(id)sender;
ほかのボタンも同様にして、
- (IBAction)meAction:(id)sender;
- (IBAction)revGeoAction:(id)sender;
- (IBAction)modeAction:(id)sender;
- (IBAction)pinAction:(id)sender;
- (IBAction)shareAction:(id)sender;
地図の移動
最初は、
プロジェクト名+ViewController.
- (IBAction)meAction:(id)sender {
// ここに追記
}
中心の経緯度と範囲
- (IBAction)meAction:(id)sender {
BMCoordinateRegion region;
region.center.latitude = 35.68918;
region.center.longitude = 139.6916;
region.span.latitudeDelta = 0.01;
region.span.longitudeDelta = 0.01;
[self.mapView setRegion:region animated:YES];
}
ここまでを実行してみましょう

Meボタンは、
BMCoordinateRegionで表す範囲は度単位でしたので、
- (IBAction)meAction:(id)sender {
BMCoordinateRegion region;
region = BMCoordinateRegionMakeWithDistance(
self.mapView.userLocation.location.coordinate,
self.mapView.userLocation.location.verticalAccuracy,
self.mapView.userLocation.location.horizontalAccuracy);
[self.mapView setRegion:region animated:YES];
}
コードで見ると簡単ですね。ここまでを実行してみましょう

逆ジオコーディング
次は、
逆ジオコーディングはBMReverseGeocoderクラスを用います。ViewControllerクラスから使用できるようプロジェクト名+ViewController.
#import <UIKit/UIKit.h>
#import "BingMaps/BingMaps.h"
@interface GihyoSample2ViewController : UIViewController<BMMapViewDelegate, >BMReverseGeocoderDelegate> { // ①
@private
IBOutlet BMMapView *mapView_;
BMReverseGeocoder *reverseGeocoder_; // ②
}
@property (nonatomic, retain) IBOutlet BMMapView *mapView;
@property (nonatomic, retain) BMReverseGeocoder *reverseGeocoder; // ③
①上記コードではBMReverseGeocoderDelgateを追記しています。ViewControllerクラスをデリゲート先に指定し逆ジオコーディング結果を受け取る処理を行います。BMReverseGeocoderDelgateには、
実装すべきメソッドが定義されています。 ②③また、
BMReverseGeocoder型のインスタンス変数reverseGeocoderも宣言しています。@propertyを使用してアクセサメソッドの自動生成も指定し、 アクセサメソッド (プロパティ) 経由でコードからアクセスするようにします。次はこれらの実装を記述しましょう。
プロジェクト名+ViewController.
@synthesize mapView = mapView_;
@synthesize reverseGeocoder = reverseGeocoder_; // 追記
続いて、
-(void)reverseGeocoder:(BMReverseGeocoder *)geocoder didFindEntity:(BMEntity *)entity {
}
-(void)reverseGeocoder:(BMReverseGeocoder *)geocoder didFailWithError:(NSError *)error {
}
イベント処理
以上で、
- (IBAction)revGeoAction:(id)sender {
self.reverseGeocoder = [[BMReverseGeocoder alloc] initWithCoordinate:self.mapView.region.center];
self.reverseGeocoder.delegate = self;
[self.reverseGeocoder start];
}
逆ジオコーディングの成功・
逆ジオコーディングに成功した場合、
コードは次のようになります。アラートの表示にはUIAlertViewオブジェクトを生成して行います。
-(void)reverseGeocoder:(BMReverseGeocoder *)geocoder didFindEntity:(BMEntity *)entity {
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:[entity adminDistrict]
message:[entity formattedAddress]
delegate:self
cancelButtonTitle:@"Ok"
otherButtonTitles:nil] autorelease];
[alert show];
self.reverseGeocoder = nil;
}
次は失敗した場合です。アラートにエラーメッセージを表示するようにしています。
-(void)reverseGeocoder:(BMReverseGeocoder *)geocoder didFailWithError:(NSError *)error {
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"Error"
message:[error localizedDescription]
delegate:self
cancelButtonTitle:@"Ok"
otherButtonTitles:nil] autorelease];
[alert show];
self.reverseGeocoder = nil;
}
ここまでを実行してみましょう。結果は図10のようになります。ただしく住所が取得できたでしょうか。日本の場合、

地図の種類の変更
次は、
- 道路地図
- 航空写真
- ラベル付き航空写真
Modeボタンをタップするたびに種類を切り替えるようコードを記述します。
地図の種類は、
- (IBAction)modeAction:(id)sender {
switch (self.mapView.mapMode) {
case BMMapModeRoad:
self.mapView.mapMode = BMMapModeAerial;
break;
case BMMapModeAerial:
self.mapView.mapMode = BMMapModeAerialWithLabels;
break;
default:
//case BMMapModeAerialWithLabels:
self.mapView.mapMode = BMMapModeRoad;
}
}
実行結果は、

マーカーの表示
地図コントロールの機能の紹介の最後は、
マーカーを地図上に追加するには、
- (IBAction)pinAction:(id)sender {
BMEntity *entity = [[[BMEntity alloc]initWithCoordinate:self.mapView.region.center
bingAddressDictionary:nil] autorelease];
[self.mapView addMarker:entity];
}
BMEntityオブジェクトは逆ジオコーディングのときにもdidFindEntityメソッドで受け取り使用していました。今回は自分で生成します。上記コードでは、
マーカーの表示はこれだけでは完了しません。マーカーを表示するためのBMMarkerView
- (BMMarkerView *)mapView:(BMMapView *)mapView viewForMarker:(id<BMMarker>)marker {
static NSString *pinIdentifier = @"PinIdentifier";
BMMarkerView *pinView = [self.mapView dequeueReusableMarkerViewWithIdentifier:pinIdentifier]; // ①
if (!pinView) {
pinView = [[BMPushpinView alloc]initWithMarker:marker
reuseIdentifier:pinIdentifier]; // ②
} else {
pinView.marker = marker;
}
return pinView;
}
①パフォーマンスの問題から、
Marker Viewを毎回 生成するのではなく、 既に作成したものがあればそれを使用します。dequeueReusableMarkerViewWithIdentifierメソッドを使用して、 指定したIDのMarker Viewを得ます。 ②Marker Viewがない場合は、
新しく生成します。BMMarkerViewクラスではなく、 派生クラスであるBMPushpinViewクラスのオブジェクトを実際には使います。BMPushipinViewの初期化のメソッドで表示するマーカー (marker変数) の指定もしています。
ここまでを実行してみましょう。Pinボタンをタップするたびに、

マーカーを削除する場合は、
- (IBAction)pinAction:(id)sender {
[self.mapView removeMarkers:self.mapView.markers];
BMEntity *entity = [[[BMEntity alloc]initWithCoordinate:self.mapView.region.center
bingAddressDictionary:nil] autorelease];
[self.mapView addMarker:entity];
}
地図の共有
最後におまけ機能としてメールの送信処理を加えます。処理を簡単にするため、
フレームワークの追加
まずメール機能を使用するために必要なフレームワークを追加します。TARGETSのプロジェクト名をクリックし、


ヘッダーの編集
次は、
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#import "BingMaps/BingMaps.h"
@interface GihyoSample2ViewController : UIViewController<BMMapViewDelegate, BMReverseGeocoderDelegate, MFMailComposeViewControllerDelegate> {
@private
IBOutlet BMMapView *mapView_;
BMReverseGeocoder *reverseGeocoder_;
}
メールの送信
それでは、
- (IBAction)shareAction:(id)sender {
// ①
if(![MFMailComposeViewController canSendMail]) {
return;
}
// ②
double lat = self.mapView.region.center.latitude;
double lng = self.mapView.region.center.longitude;
NSString *body = [NSString stringWithFormat:@"http://www.bing.com/maps/?q=%f,%f", lat, lng];
// ③
MFMailComposeViewController *ctl = [[[MFMailComposeViewController alloc]init] autorelease];
ctl.mailComposeDelegate = self;
[ctl setMessageBody:body isHTML:NO];
[self presentModalViewController:ctl animated:YES];
}
①メール関連の処理は、
MFMailComposeViewControllerクラスを使用します。最初にメールが送信可能かcanSendMailメソッドでチェックします。 ②メール本文となるBing MapsへのURLを作成します。
③MFMailComposeViewControllerオブジェクトを作成し、
メール本文を設定し、 メール送信の画面を表示します。
メール送信後の成功・
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
if (error != nil) {
UIAlertView *alert = [[[UIAlertView alloc]initWithTitle:@"Error"
message:[error localizedDescription]
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil] autorelease];
[alert show];
}
[self dismissModalViewControllerAnimated:YES];
}
以上が、

おわりに
今回はここまでです。いかがでしたでしょうか。Bing Maps iOS Controlを利用したiPhone・
Bing Maps iOS Controlの機能はいかがでしたか。連載で使用していない細かな機能はありますが、
iPadについては連載で触れていませんが、
また、