UINavigationControllerのアニメーションをカスタマイズする方法

UINavigationControllerでビューコントローラーをpush/popするときのアニメーションはスライドです。このアニメーションをカスタマイズしてみます。

ここではフェードを行ってみます。

まずはpushです。

- (IBAction)push {
    SubViewController *subViewController = [[[SubViewController alloc] initWithNibName:nil bundle:nil] autorelease];
    subViewController.view.frame = self.view.bounds;
    subViewController.view.alpha = 0.0;
    [self.view addSubview:subViewController.view];
 
    [UIView transitionWithView:subViewController.view duration:1.0 options:UIViewAnimationOptionCurveEaseInOut animations:^(void) {
        subViewController.view.alpha = 1.0;
    } completion:^(BOOL finished) {
        [self.navigationController pushViewController:subViewController animated:NO];
    }];
}

pushする対象はSubViewControllerです。現在のビューと同じサイズに設定して、透明にして、現在のビューにaddSubviewします。
アニメーションですが、alphaを1.0にして不透明にします。アニメーションが完了したらpushViewController:animated:でpushを行います。animatedにはNOを指定して、デフォルトのスライドアニメーションを行わないようにします。

次にpopです。

- (IBAction)pop {
    NSArray *viewControllers = [self.navigationController viewControllers];
    NSUInteger previousIndex = [viewControllers count] - 2;
    UIViewController *previousViewController = [viewControllers objectAtIndex:previousIndex];
    previousViewController.view.alpha = 0.0;
    [self.view addSubview:previousViewController.view];
 
    [UIView transitionWithView:previousViewController.view duration:1.0 options:UIViewAnimationOptionCurveEaseInOut animations:^(void) {
        previousViewController.view.alpha = 1.0;
    } completion:^(BOOL finished) {
        [self.navigationController popViewControllerAnimated:NO];
    }];
}

viewControllers から、pop後に表示される前のビューコントローラーを取得します。viewControllers配列の後ろから2番目に入っています。このコントローラーのビューのalphaを0.0に設定して透明にして、現在のコントローラーのビューに載せます。
アニメーションも同様にalphaを1.0に設定して、不透明にします。アニメーションが終了したらpopViewControllerAnimated:でpopします。これもNOを指定してデフォルトアニメーションを行わないようにします。

このように、UINavigationControllerでのフェードアニメーションは、push/popはどちらも、これから表示するビューを上に載せて、透明から不透明にアニメーションを行い、アニメーションが終了したタイミングでpush/popを行うことになります。