現在、Navigation ControllerからTop View Controllerをポップオフするときにコードを実装する必要があります。 View ControllerがNavigation Controllerスタックからポップされていることを検出する方法はありますか?
私はプロジェクトでviewWillDisappear
を使用しているため、viewDidDisappear
またはsplitview
を使用しないでください。マスタービューで別の行を選択するとviewWillDisappear
/viewDidDisappear
メソッドもトリガーします。
以下に示すように、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が親から削除されていることを示すブール値を返します。
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
が意味をなす場合があります。ただし、親コンテナービューコントローラーからのプッシュとポップを本当に探している場合は、上記のメソッドが必要です。
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*/
}
}
これがお役に立てば幸いです
View Controllerが削除される前に知る必要がなく、単にポップされたことを知る必要がある場合は、deinit
を使用することもできます。
class ViewController: UIViewController {
deinit {
// View controller has been popped/dismissed and it's being released
}
}
このメソッドは、コーディネーターまたは他のデリゲートに通知するのに適しています。