20

I know that starting with iOS5 and the new UIViewController containment methods, you are supposed to call these methods together with addChildViewController:, removeFromParentViewController: and the transition method. I also know the proper order of calling them in the three scenarios. What I don't know is what exactly these methods do?

If these were merely override points for subclasses of UIViewController I guess we wouldn't be required to call super when overriding. What can/will go wrong if I don't call willMoveToParentViewController: nil before removing a view controller or didMoveToParentViewController: self?

konrad
  • 1,664
  • 2
  • 17
  • 36

2 Answers2

12

In addition to what has been said, they do call some delegate methods:

addChildViewController calls [child willMoveToParentViewController:self]

and removeFromParentViewController: calls [child didMoveToParentViewController:nil]

Also, they modify the childViewControllers property, which holds an array of child view controllers.

Guillaume
  • 4,331
  • 2
  • 28
  • 31
  • 3
    Yes, I know, 'add' and 'remove' calls one method automatically (willMove... and didMove... respectively) and requires you to call the other one manually. I think I have no problem with understanding what 'add' and 'remove' do - it's seems pretty straghtforward. I just feel a little confused as to what the 'will' and 'did' actually do. – konrad Oct 16 '12 at 14:05
  • 2
    The `will` and `did` don't have a particular implementation, you call them on the child controller, and if you don't, then they're simply not called... which might be a problem if the child controller implemented them and relied on them. In my answer I mistakenly called them "delegate methods", but that's almost what they are, they function as optional delegate methods, and the child might use them to do some setup or clean up. Any UIViewController subclass might override them, and if you implement a container controller, you're supposed to respect this behavior and call them. – Guillaume Oct 16 '12 at 14:41
  • 4
    To be clear, UIViewController's `willMoveToParentViewController:` and `didMoveToParentViewController:` don't do anything. However, any subclass allows them to be overridden, so if you don't call them, you won't break a bare UIViewController, but you will break subclasses that rely on it (for instance: say a subclass wants to release an object when it is removed from a parent view controller, if you don't call the method, then it will never release the object). – Guillaume Oct 16 '12 at 14:46
  • Ok, that makes it clear. So it is a kind of optional protocol. Recently I was trying to hunt some bugs in view controller hierarchy management, and found out I forgot to call these in a few places. That's when I started to wonder what can go bad in such case. It turns out that as long as I don't override these in UIViewController subclasses which I add/remove it shouldn't affect anything (which doesn't mean you shouldn't call them, obviously). Thanks a lot! – konrad Oct 16 '12 at 15:22
  • @Guillaume -- I've got one for you! What if it is a **NEW** view controller which you just created (instantiateViewControllerWithIdentifier) .. in that case, is it totally safe to NOT CALL didMoveToParentViewController .. since it is not moving? the advantage of not calling it is you avoid the infuriating 2x viewWillAppear issue. cheers! – Fattie Aug 31 '14 at 14:57
  • @Guillaume, can you please provide the step of using containerview – Ravi Ojha Feb 05 '15 at 07:05
1

There are many answers to this:

  1. They are there and you are supposed to call them where applicable to always uphold the pattern. That way, if you change superclasses from UIViewController to your own view controller, you won't have to worry about where you followed the entire pattern.

  2. They are better places to hook into than telling everyone to override addChildViewController:. As you say, mis-managing willMoveToParentViewController: sounds like it's less dangerous than mis-manging addChildViewController:, especially if you forget to call super.

  3. UIViewController probably depends on you upholding the pattern. Maybe it will deem the state inconsistent if it knows that it has received addChildViewController: but never gets the other two messages. Whether this happens due to UIViewController doing book-keeping to lure you into upholding the full pattern or whether you really do mess up its internal state is a fun guessing game, but also something that may change in any iOS release. Things may break badly. That's why the pattern is there, for Apple to tell you that as long as you do this, we will keep things working no matter what.

Questioning a pattern is good, but there are many potential negatives that come with trying to cut your conformance of a pattern to the bone. Unless the pattern is ridiculously involved, it's usually just easier to conform to it.

Jesper
  • 7,477
  • 4
  • 40
  • 57
  • 2
    I don't mean to question using these methods. If Apple docs say 'you must' call them, there sure is a reason behind it. I just hope that someone with a bit more experience and knowledge of the mechanism of nesting UIViewControllers will explain it in a bit more detail than the official docs which only say it 'informs' the child view controller about the change. My theory is that it allows some preparation and cleanup if you want the transition to be animated, but that's just a guess. – konrad Oct 16 '12 at 14:13
  • Oh, that's what it's going to be used for if you subclass a `UIViewController`. My point was that even if it did nothing, knowing that would not make calling `super` something you should avoid. Maybe it's best summed up by "it makes it a lot less messy because you won't have to override `addChildViewController:`" (point 2). – Jesper Oct 16 '12 at 14:48