MapKitめも アノテーションにある矢印ボタンタップ時の動きをiOS標準の地図アプリと同じようにしたい

カーネルとか全く関係ないんですけども、iOS標準の地図アプリだと矢印ボタンをタップすると新しいviewがスライドしながら出てくるのでそれと同じことをしたかったと。

こんな画面で→をタップすると、
f:id:masami256:20130515215002p:plain

viewがスライドして出てきて、「Back」ボタンで地図に戻りたい感じです。
f:id:masami256:20130515215358p:plain
viewになにも無いからナビゲーションバーのところ以外真っ白ですけどw

動き的にはUINavigationBarっぽい動きなのでUINavigationXXXXの機能(UINavigationController、UINavigationItemとか)を使えばいけるかなと思いつつ調べた結果、UINavigationControllerとUINavigationItemを使えばできたのでメモっておきます。基本的にはマップとか関係なく通常のUINavigationControllerの使い方と一緒だと思います。

まずは、delegateのdidFinishLaunchingWithOptions()から。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.viewController = [[NDViewController alloc] initWithNibName:@"NDViewController" bundle:nil];
    self.navContoller = [[UINavigationController alloc] initWithRootViewController:self.viewController];
    [self.navContoller setNavigationBarHidden:NO];
    self.window.rootViewController = self.navContoller;
    
    [self.window makeKeyAndVisible];
    return YES;
}

ここはUINavigationControllerクラスのself.navContollerをinitWithRootViewController()で初期化。rootViewControllerにはUINavigationControllerのインスタンスをセットしておく。

次に地図(MKMapView)があるほうのviewクラスでviewDidLoad()の処理で検索バー(UISeachBar)をUINavigationItemにセットをする。これは個人的に追加したかっただけですけどもw

    CGRect rect = CGRectMake(0, 0, 320, 44);
    
    self.searchBar = [[UISearchBar alloc] initWithFrame:rect];
    self.searchBar.delegate = self;
    self.searchBar.showsCancelButton = YES;
    self.searchBar.placeholder = @"ミャーと鳴く四足歩行生物";
    
    self.navigationItem.titleView = self.searchBar;
    self.navigationItem.titleView.frame = rect;

ここで悩んだのは最初はdelegateのほうで初期化したnavContollerが持ってるnavigationItemに検索バーを設置するのかと思ってたけどそれだと表示されず、じゃあ、navigationItemのインスタンスを作ってそれをnavContollerにセットしてみるとかやってたんですが、それでダメでもしかしたらと思ってself.navigationItemで試したら上手くいったという次第です。。。

そして矢印が押されたときはこんな感じです。ボタンが押されたときのイベントをとるのでMKMapViewDelegateのメソッドを実装します。

- (void)mapView:(MKMapView*)mapView annotationView:(MKAnnotationView*)view
calloutAccessoryControlTapped:(UIControl*)control
{
    NDAnnotationData *data = view.annotation;
    
    NDCalloutViewController *annoview = [[NDCalloutViewController alloc] initWithAnnotationData:data];
    [self.navigationController pushViewController:annoview animated:YES];
}

NDCalloutViewControllerがviewのクラスでinitWithAnnotationDataはデータを渡したいから作った関数なのでそれが必要でなければ普通にviewを作るだけですね。
viewを作ったらUINavigationControllerクラスのpushViewController()でviewをpushすればokです。