ViewControllerで戻るボタンのタップを検知する

  • 122
    Like
  • 3
    Comment
More than 1 year has passed since last update.

ViewControllerによって自動で生成された戻るボタンをユーザーに押された時の処理を検知したいときに調べたメモ。みなさんもユーザーのログ関係でそういうことをしないといけない要件があったりするのではないかなと。

StackOverflowみるといくつか方法があった
http://stackoverflow.com/questions/5217992/back-button-callback-in-navigationcontroller-in-ios

3つ紹介しておく。

viewWillDisappear:時に判定

viewWillDisappear:時に自分自身がnavigationControllerのコンテナに追加されているかを判定することによって検出できる

- (void)viewWillDisappear:(BOOL)animated
{
    if (![self.navigationController.viewControllers containsObject:self]) {
        //戻るを押された
        NSLog(@"back");
    }

    [super viewWillDisappear:animated];
}

viewWillDisappear:はライフサイクルとして動作しているメソッドなので、戻るを押されてこのViewControllerがpopされた後に動作するためこの判定でも検知はできるが、下記のようなお約束の上で成り立っている

  • ViewControllerがpopされた
  • popされたから画面から消える
  • 画面から消えるからviewWillDisappear:が動作する
  • ViewControllerが破棄される

仕様上、popされた際に必ずviewWillDisappear:が起きるわけではなく、画面の表示が無くなった際に動作するので順番的には妥当っぽく見える。

上手く説明できないけど、ライフサイクルに依存するのは少し綱渡り的な気がするし人に教える時はこの方法はやめとくかな。

Appleのリファレンスを調べると、ライフサイクルを使う方法にはもうひとつやり方がある。それはisMovingFromParentViewControllerプロパティを調べるやり方で、このプロパティ自体の説明としても妥当な使い方をしている

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];

    if (self.isMovingFromParentViewController) {
        //親から削除されているかどうかなので戻るだけでなく閉じても判定
        NSLog(@"isMovingFromParentViewController");
    }

}

ただ、これは戻るボタンのタップ以外に、この親ViewControllerがモーダルの場合には「戻るボタン」だけでなく閉じても動作して同じように判定してしまう。

didMoveToParentViewController:で判断

didMoveToParentViewController:メソッドはコンテナがViewControllerを追加した後にその追加されたViewControllerで実行される。これを使えばpopされたとこを検知できるので戻るを判定できる(モーダルで閉じるにしても動作しない)。

//追加もしくは削除された後に動作する
- (void)didMoveToParentViewController:(UIViewController *)parent
{
    if (![parent isEqual:self.parentViewController]) {
        NSLog(@"back");
    }
}

最初self.parentViewControllerはnilだろうしnilかどうかで判断すればいいのでは...と思ったがこのメソッドの前に他のコンテナに追加されnilでないこともあるんだろう。

また、削除された時はdidMoveToParentViewController:の引数parent自体がnilのはずなのでparentがnilだったら削除されてると判断できなくもない気がする。より厳密さを求めて特定の親ViewControllerを比較したいためにisEqaul:メソッドで比較しているのだと思う(ただ戻るを押した際の動作的にはnilとnilの比較になっていた)。

didMoveToParentViewController:ってどんなんだっけとググったら昔書いた自分のメモがあった
http://qiita.com/yimajo/items/a5e16fa0f9c332a55ccf