web-dev-qa-db-ja.com

View ControllerがNavigation Controllerからポップされているかどうかを検出する方法は?

現在、Navigation ControllerからTop View Controllerをポップオフするときにコードを実装する必要があります。 View ControllerがNavigation Controllerスタックからポップされていることを検出する方法はありますか?

私はプロジェクトでviewWillDisappearを使用しているため、viewDidDisappearまたはsplitviewを使用しないでください。マスタービューで別の行を選択するとviewWillDisappear/viewDidDisappearメソッドもトリガーします。

39
aresz

以下に示すように、View ControllerのisMovingFromParentViewControllerプロパティを使用して、ビューがポップされているかどうかを検出できます。

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    if ([self isMovingFromParentViewController])
    {
        NSLog(@"View controller was popped");
    }
    else
    {
        NSLog(@"New view controller was pushed");
    }
}

isMovingFromParentViewController

View Controllerが親から削除されていることを示すブール値を返します。

81
Nishant

UPDATE 20150430

ファットマンのフィードバック(下記の最初のコメント)に基づいて、私は1年以上前にこの質問に答えてから何かが変わったかどうかに興味がありました。簡単なサンプルアプリを作成しましたが、興味深い結果が得られました。

オプション1、例

https://github.com/greymouser/TestNVC

私は8.xより前のバージョンを簡単にテストする能力がないので、それ以降何かが変わったかどうかはわかりません。ただし、最初に説明した動作は引き続き発生します。 ただし、、テストアプリをまとめたおかげで、以前はなかった奇妙なことに気付きました。

{will,did}MoveToParentViewControllerだけに依存している場合、rootVCで最初の非rootVCを親!= nilでプッシュすると、偽のdidMoveToParentViewController:呼び出しに気付きました(削除されずに追加されたことを意味します)。通常、NVCに「永続的な」rootVCがあり、コールバックを実装していなかったため、最初の回答の頃にはこれに遭遇しませんでした。ロギングをLOG_WILL_DID_MTPVC(ViewController.mに)に設定したサンプルアプリを参照してください。これは-スペース用に編集された-私が見たもののスナップショットです:

TestNVC[] -[vc(rootVC) willMoveToParentViewController [entering]
TestNVC[] -[vc(rootVC) didMoveToParentViewController [entering]
TestNVC[] -[vc(1) willMoveToParentViewController [entering]
TestNVC[] -[vc(rootVC) didMoveToParentViewController [entering]  # <-- this is odd
TestNVC[] -[vc(1) didMoveToParentViewController [entering]
...

私の元の答えは、{will,did}MoveToParentViewControllerを単独で使用することを提案しました。これは、この動作を処理する「ワンストップショップ」であったためです。ただし、rootVCへの誤った呼び出しを確認したため、{will,did}MoveToParentViewControllerと標準のUINavigationControllerDelegateコールバックを組み合わせることをお勧めします。サンプルアプリでこの動作を行うには、ロギングをLOG_WILL_DID_MTPVC_LEAVING_AND_NVC_WILL_DID_SHOW_VCに設定します。次のように表示されます。

TestNVC[] -[nvcD willShowViewController]: rootVC
TestNVC[] -[nvcD didShowViewController]: rootVC
TestNVC[] -[nvcD willShowViewController]: 1
TestNVC[] -[nvcD didShowViewController]: 1
TestNVC[] -[nvcD willShowViewController]: 2
TestNVC[] -[nvcD didShowViewController]: 2
TestNVC[] -[vc(2) willMoveToParentViewController [leaving]
TestNVC[] -[nvcD willShowViewController]: 1
TestNVC[] -[vc(2) didMoveToParentViewController [leaving]
TestNVC[] -[nvcD didShowViewController]: 1
TestNVC[] -[vc(1) willMoveToParentViewController [leaving]
TestNVC[] -[nvcD willShowViewController]: rootVC
TestNVC[] -[vc(1) didMoveToParentViewController [leaving]
TestNVC[] -[nvcD didShowViewController]: rootVC

...そしてこれは今ではもっと理にかなっています。

オプション2

私が検討しなかった別のオプションは、NVC sublcassを使用して、- pushViewController:animated:- popViewControllerAnimated:をオーバーライドし、必要な動作をVCプッシュされる、または= VCこれはポップから返されました。これを試みる場合は、オーバーライドでsuperを呼び出すことを忘れないでください。)

サマリーの更新

そのため、これを修正する機会を与えてくれたファットマンに感謝します。私の答えはmore正しいと思う。ただし、それが「完全に非真実」であったかどうかはあまりわかりません。 ;-)

[〜#〜] original [〜#〜]

説明したとおりの動作が探しているものである場合は、子View Controllerで次をオーバーライドします。

- (void)willMoveToParentViewController:(UIViewController *)parent;
- (void)didMoveToParentViewController:(UIViewController *)parent;

willMoveToParentViewController:は、入力時に親!= nilで呼び出され、終了時に親== nilで呼び出されます。 didMoveToParentViewController:は常に親!= nilを持ちます。

時々、viewDidDisappearが意味をなす場合があります。ただし、親コンテナービューコントローラーからのプッシュとポップを本当に探している場合は、上記のメソッドが必要です。

24
greymouser

For Swift Users(Swift 3-4.2):

View Controllerがスタックからポップされていることを検出したかったので、viewWillDisappearまたはviewDidDisappearコールバックを使用できませんでした。これらのコールバックはView Controllerが起動されていないときに呼び出されるためですスタックからポップされたときではなく、表示されます。

ただし、以下を実行することにより、Navigation Controller Delegates UINavigationControllerDelegateを使用できます。

コントローラーをUINavigationControllerDelegateに適合させます:

class ViewController : UIViewController {

      override func viewDidLoad() {
          super.viewDidLoad()
          self.navigationController?.delegate = self
      }

}




extension ViewController : UINavigationControllerDelegate {

     override func willMove(toParentViewController parent: UIViewController?) {

     /*You can detect here when the viewcontroller is being popped*/

     }

}

これがお役に立てば幸いです

0
MhmdRizk

View Controllerが削除される前に知る必要がなく、単にポップされたことを知る必要がある場合は、deinitを使用することもできます。

class ViewController: UIViewController {

    deinit {
        // View controller has been popped/dismissed and it's being released
    }
}

このメソッドは、コーディネーターまたは他のデリゲートに通知するのに適しています。

0
Eneko Alonso