How does View Controller Containment work in iOS 5?

Solution 1:

The UIViewController docs are pretty clear on when and when not to call willMove/didMove methods. Check out the "Implementing a Container View Controller" documentation.

The docs say, that if you do not override addChildViewController, you do not have to call willMoveToParentViewController: method. However you do need to call the didMoveToParentViewController: method after the transition is complete. "Likewise, it is is the responsibility of the container view controller to call the willMoveToParentViewController: method before calling the removeFromParentViewController method. The removeFromParentViewController method calls the didMoveToParentViewController: method of the child view controller."

Also, there is an example worked out here and sample code here.

Good Luck

Solution 2:

This part is not correct:

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

According to the docs:

When your custom container calls the addChildViewController: method, it automatically calls the willMoveToParentViewController: method of the view controller to be added as a child before adding it.

So you don't need the [vc willMoveToParentViewController:self] call. It is done automatically when you call [self addChildViewController:vc]. Here's the code sample again:

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

For removing view controllers:

The removeFromParentViewController method automatically calls the didMoveToParentViewController: method of the child view controller after it removes the child.

Presumably this call is [oldVC didMoveToParentViewController:nil].

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