presentModalViewControllerで表示した2階層以上の画面から一気に戻る方法

presentModalViewControllerした画面はdismissModalViewControllerAnimatedで閉じるので、push/popのときと違い、画面を一気に戻ることができません。
そんなときにどうするかというとこうします:


1. まず、呼び出し元の画面から、画面が閉じたときのイベントを子画面に渡します:

@implementation ParentViewController

- (void)foo {
    ChildViewController* child = [[[ChildViewController alloc] initHogeHoge] autorelease];
    [child setCloseDelegate:self action:@selector(onCloseChild)];

    [self.navigationController presentModalViewController:child animated:YES];
}

...
@end
@interface ChildViewController : UIViewController
{
    id parent;
    SEL closeAction;
}
@end

- (void)setCloseDelegate:(id)parent action:(SEL)action;


2. 次に、dismissModalViewControllerAnimatedしたときにcloseフラグを立てます。

#import <boost/utility/value_init.hpp>

@interface ChildViewController : UIViewController
{
    ...
    boost::initialized<bool> isClosed;
}
@end
@implementation ChildViewController

// ナビゲーションバーのleftButtonとか、画面内の閉じるボタンとかが押された。
- (void)onCloseButton {
    isClosed.data() = true;
    [self dismissModalViewControllerAnimated:YES];
}

...
@end

3. ChildViewControllerのdeallocで親の画面に閉じたイベントを送ります:

@implementation ChildViewController
...

- (void)dealloc {
    if (isClosed.data() && parent && [parent respondsToSelector:closeAction])
        [parent performSelector:closeAction];

    ...
}
@end

4. 最後に、子画面が閉じたときのイベントを受け取った親画面が自身を閉じます:

@implementation ParentViewController

- (void)onCloseChild {
    [self dismissModalViewControllerAnimated:YES];
}

...
@end

これで、子画面が閉じ終わると同時に親画面が閉じ、サッサッと次々画面が閉じていきます。