iOS 5でView Controller Containmentはどのように機能しますか?


108

WWDC 2011のセッション102で、Appleはに類似したカスタムビューコントローラコンテナを作成する機能、あるビューコントローラ封じ込め、導入UITabBarControllerUINavigationControllerなどを。

例を何度か見ました。このパターンに関連付けられているメソッドはさまざまですが、正確に把握するのは少し困難でした。私はここで私が起こっていると思うことを投稿し、コミュニティが私の疑いを確認するかどうかを確認します。

シナリオ1:親がない状態から新しい親View Controllerに移動する

[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];

最初の2行は指定された順序で発生する必要がありますか、それとも逆にすることができますか?

シナリオ2:親View Controllerから親View Controllerなしに移動する

[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];

電話も必要[vc didMoveToParentViewController:nil]ですか?セッション102の例で、このシナリオではこれを行いませんでしたが、それが省略であったかどうかはわかりません。

シナリオ3:ある親View Controllerから別のView Controllerへの移動

各親ビューコントローラーのロジックがカプセル化されるため、これは次のように発生する可能性があります。

// In the old parent
[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];

// In the new parent
[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view];
[vc didMoveToParentViewController:self];

ご質問

私の主な質問はこれです:これは一般的にビューコントローラーの封じ込めがどのように機能するかですか?上記のメカニズムは正しいですか?

呼び出すwillMoveToParentViewController前に呼び出す必要がありますaddChildViewControllerか?これは私には論理的な順序のように見えますが、厳密に必要ですか?

呼び出しdidMoveToParentViewController:nil後に呼び出す必要がありますremoveFromParentViewControllerか?

回答:


72

UIViewControllerドキュメントはときといないときのコールへのかなりはっきりしているwillMove/ didMoveメソッド。「Container View Controllerの実装」ドキュメントを確認してください。

ドキュメントによると、をオーバーライドしない場合addChildViewControllerwillMoveToParentViewController:メソッドを呼び出す必要はありません 。ただしdidMoveToParentViewController:、遷移が完了した後でメソッドを呼び出す必要があります。「同様に、willMoveToParentViewController:メソッドを呼び出す前にメソッドを呼び出すのはコンテナービューコントローラーの責任ですremoveFromParentViewController。メソッドは子ビューコントローラーのremoveFromParentViewControllerメソッドを呼び出しますdidMoveToParentViewController:。」

また、働いた例があり、ここで、サンプルコードをここに

幸運を


17
なるほど、そうaddChildViewControllerでバランスされなければならないdidMoveToParentViewControllerwillMoveToParentViewControllerしてバランスする必要がありますremoveFromParentViewController。これはまさに私が探していたものです。私がドキュメントでどのようにそれを逃したかわかりません。
Gregory Higley、2011

何故なの?willMoveToParentViewControllerを呼び出す必要がないのに、didMoveToParentViewControllerを呼び出す必要があるのはなぜですか?
user4951 2012年

それはドキュメントが言うことなのでです。Appleは明らかに私たちが知る必要がないと感じています。

7
理由はアニメーションのためです。たとえば、独自のナビゲーションコントローラを作成しているとします。スライドインアニメーションの開始時に 'willMove'を呼び出し、アニメーションの終了時に 'didMove'を呼び出す必要があります。これで、アニメーションの開始時に「addChild」を呼び出すと、自動的に「willMove」が呼び出されます。ただし、アニメーション(存在する場合)がいつ終了するかは認識できないため、アニメーションの最後に(またはアニメーションがない場合はすぐに)手動で「didMove」を呼び出す必要があります。
Chris

2
また、「スライドアウト」アニメーションについては、たとえば子が削除されている場合、アニメーションの開始時に手動で「willMove」を呼び出す必要があります。そうしないと、uikitが子VCの「viewWillDisappear」を呼び出すタイミングがわからないためです。アニメーションの最後に、removeFromParentViewControllerを呼び出すと、自動的に「didMove」を呼び出すことができます。
Chris

23

この部分は正しくありません:

[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];

ドキュメントによると:

カスタムコンテナがaddChildViewController:メソッドを呼び出すと、追加する前に、子として追加されるビューコントローラのwillMoveToParentViewController:メソッドが自動的に呼び出されます。

だからあなたは[vc willMoveToParentViewController:self]電話をする必要はありません。を呼び出すと自動的に行われます[self addChildViewController:vc]。もう一度コードサンプルを示します。

[self addChildViewController:vc];
// [vc willMoveToParentViewController:self] called automatically
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];

View Controllerを削除する場合:

removeFromParentViewControllerメソッドは、子を削除した後、子ビューコントローラのdidMoveToParentViewController:メソッドを自動的に呼び出します。

おそらくこの呼び出しは[oldVC didMoveToParentViewController:nil]です。

[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];
// [vc didMoveToParentViewController:nil] called automatically

他の方法で実行した場合、機能しているように見えても、presentingViewControllerがpresentedViewControllerに設定されていないようです。
エイドリアン

ドキュメントは、didMoveToParentViewController 「addChildViewController:メソッドを呼び出した直後」と呼び出しますが、実際に子サブビューを追加するタイミングは指定されていません。誰もがこれを間違っているのだろうか。これを確認できるApple Docsの例はありますか?
Robert

注:あなたがやる呼び出す必要があるwillMoveToParentViewController前にaddChildViewController、あなたが移動しているアイテムは、オーバーライドしてカスタムクラスであればaddChildViewController(自分のオーバーライドが内部的に呼び出さない限り)
bunkerdive
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.