地図アプリの開発で問題になるポイントをコード付きで解説します。
iPhone/iPad/iPodアプリ開発において、地図と連動させるものを作ろうと思ったら
まず浮かび上がるのがMapKitでしょう。
これは、GoogleMapのSDKであり、GPS機能と連動させて現在位置を表示したり、
マップにピンを立てて目的地を地図付きで説明したりと、
地図情報を使ったアプリではとても重宝します。
(GPSを使った位置情報の取得は別のフレームワークを使用します。)
とても高性能で、とてもよく使うMapKitのGoogleMapですが、
使い方には注意する事があります。
それは、マップ上に表示されるGoogleのロゴです。
もし、仮にMapKitを使用しているのにGoogleロゴが見えない状態になる場合は、
アップルのアプリ申請を通す事は出来ません。
地図のサイズを動的に変更させたり、カーナビや道案内等で地図を回転させたりすると、
結構Googleロゴが隠れてしまう事があります。
しかし、そんな状態で申請しても、アップルは容赦なくリジェクトしてきます。
MapKitを使う限り、Googleロゴは必ず見えるようにしておく必要があります。
今回は、そんなGoogleロゴの位置を変更する方法です。
Googleロゴのインスタンスを取得する方法でもあるので、
位置を動的に変更する事も可能です。
Googleロゴのインスタンスを取得しよう
概要から説明致しますと、MapKitのViewをオーバーライドし、
その上で自分のViewの中からロゴを探しだしてインスタンスをキャッチします。
まずはいきなり答えですがコードを参照して下さい。
ヘッダファイルは下記の様に記述します。
MKMapView+Additions.h
#import <Foundation/Foundation.h> #import <MapKit/MapKit.h> @interface MKMapView (Additions) @end
MapKitのMKMapViewですね。
続いて実装内容は下記の通りです
MKMapView+Additions.m
#import "MKMapView+Additions.h" @implementation MKMapView (Additions) //------------------------------------------------------------------------------ // グーグルのロゴを見つけ出し、返却する //------------------------------------------------------------------------------ -(UIImageView*)googleLogo { UIImageView* img_view = nil; for( UIView* sub_view in self.subviews ){ if( [sub_view isMemberOfClass:[UIImageView class]] ){ img_view = (UIImageView*)sub_view; break; } } return( img_view ); } @end
MKMapViewが持つViewの中からUIImageViewのものを探し当てます。
self.subviewsを順に走査し、isMemberOfClassのクラス判定にてUIImageViewのものを探しあて、
返却します。
また、MKMap毎(地図毎)にロゴが存在しますので、インスタンスメソッドとして定義してあります。
該当するインスタンスで当メソッドを起動する事によって、
該当のMAPにあるロゴのインスタンスが取得出来ます。
これは、Viewが構築された後に探し当てる事になるので、
ライフサイクル的に言うとviewDidApperの中等で呼び出しましょう。
呼び出し方は下記を参考にして下さい。
実際にロゴを取得し、位置を変更してみよう
早速、先ほど作成したクラスを利用し、
使う側の実装について解説したいと思います。
まずは下記コードをご覧下さい。
hogeMap.h
#import <UIKit/UIKit.h> #import "MKMapView+Additions.h" @interface hogeMap : UIViewController <MKMapViewDelegate> { // MAPビュー MKMapView* topMapView; } @property (nonatomic,retain) MKMapView* topMapView;
ヘッダでは、先程作成したMKMapView+Additions.hを読み込みます。
そして、MKMapViewとしてメンバを定義します
そして使う側の実装です。
hogeMap.m
#import "hogeMap.h" @implementation hogeMap @synthesize topMapView; //------------------------------------------------------------------------------ // viewの初回構築 //------------------------------------------------------------------------------ -(void)viewDidLoad { [super viewDidLoad]; // マップビューの生成 self.topMapView = [[[MKMapView alloc] init] autorelease]; [self.topMapView setFrame:CGRectMake( 0, 0, 640, 960 )]; [self.topMapView setMapType:MKMapTypeStandard]; [self.topMapView setDelegate:self]; [self.mapBaseView addSubview:self.topMapView]; self.topMapView.showsUserLocation = NO; } //------------------------------------------------------------------------------ // view表示後の処理 //------------------------------------------------------------------------------ -(void)viewDidAppear:(BOOL)animated { // MKMapViewのインスタンスからロゴ取得メソッドを呼び、ロゴを取得する UIImageView *logo = [self.topMapView googleLogo]; if( logo == nil ) return; // ロゴのフレームを取得 CGRect frame = logo.frame; // 位置を決定する frame.origin.y = 340; frame.origin.x = 10; // 位置を反映させる logo.frame = frame; // 地図の動きの影響を受けない様にselfに設置 [self.view addSubview:logo]; [super viewDidAppear:animated]; } //------------------------------------------------------------------------------ // 破棄 //------------------------------------------------------------------------------ -(void)dealloc { self.topMapView = nil; [super dealloc]; } @end
ポイントとしては、MKMapViewのviewが構築されてから操作する事です。
ですので、viewDidAppearで実装しましょう。
後はフレームを取得出来ますので、サイズや位置、その他のプロパティも
普通のUIImageViewとして扱えます。
これでGoogleロゴを好きな位置、好きなサイズに加工する事が出来ます。
ちなみに、ios6からはデフォルトがGoogleMapでは無くなりましたので、
近いうちにGoogleMapをオーバーレイするやり方と共に
再度解説出来たらと思います。