views:

14024

answers:

8

I've read numerous posts about people having problems with viewWillAppear when you do not create your view heirarchy JUST right. My problem is I can't figure out what that means.

If I create a RootViewController and call addSubView on that controller, I would expect the added view(s) to be wired up for viewWillAppear events.

Does anyone have an example of a complex programmatic view heirarchy that successfully recieves viewWillAppear events at every level?

Apple Docs state:

Warning: If the view belonging to a view controller is added to a view hierarchy directly, the view controller will not receive this message. If you insert or add a view to the view hierarchy, and it has a view controller, you should send the associated view controller this message directly. Failing to send the view controller this message will prevent any associated animation from being displayed.

The problem is that they don't describe how to do this. What the hell does "directly" mean. How do you "indirectly" add a view.

I am fairly new to Cocoa and iPhone so it would be nice if there were useful examples from Apple besides the basic Hello World crap.

Any help is greatly appreciated...

+3  A: 

I've been using a navigation controller. When I want to either descend to another level of data or show my custom view I use the following:

[self.navigationController pushViewController:<view> animated:<BOOL>];

When I do this, I do get the viewWillAppear function to fire. I suppose this qualifies as "indirect" because I'm not calling the actual addSubView method myself. I don't know if this is 100% applicable to your application since I can't tell if you're using a navigation controller, but maybe it will provide a clue.

Josh Gagnon
+6  A: 

I've run into this same problem. Just send a viewWillAppear message to your view controller before you add it as a subview. (There is one BOOL parameter which tells the view controller if it's being animated to appear or not.)

[myViewController viewWillAppear:NO];

Look at RootViewController.m in the Metronome example.

(I actually found Apple's example projects great. There's a LOT more than HelloWorld ;)

lajos
Actually, you should call viewWillAppear after you add it to the subview. Otherwise, IBOutlets/IBActions won't be wired up.
4thSpace
Yes, afterwards. Created subview from XIB, viewWillAppear wasn't called. Call it by myself and everything works just fine.
JOM
Thank you! This was exactly it for me. I was manually adding a subview via `[scrollView addSubview:controller.view];`. I added the line `[controller viewWillAppear:NO];` afterwards and voila! Worked like a charm.
Rob S.
A: 

I'm not 100% sure on this, but I think that adding a view to the view hierarchy directly means calling -addSubview: on the view controller's view (e.g., [viewController.view addSubview:anotherViewController.view]) instead of pushing a new view controller onto the navigation controller's stack.

Martin Gordon
+8  A: 

If you use a navigation controller and set its delegate, then the view{Will,Did}{Appear,Disappear} methods are not invoked.

You need to use the navigation controller delegate methods instead:

navigationController:willShowViewController:animated:
navigationController:didShowViewController:animated:
mmalc
I hadn't set my navigation controller's delegate and still the method was not getting called. Anyway, I set it and then I used the methods you mention above. Thanks.
Dimitris
+1  A: 

I think that adding a subview doesn't necessarily mean that the view will appear, so there is not an automatic call to the class's method that it will

A: 

Just call the subView viewWillAppear from your view viewWillAppear.

Helen
+1  A: 

I just had the same issue. In my application I have 2 navigation controllers and pushing the same view controller in each of them worked in one case and not in the other. I mean that when pushing the exact same view controller in the first UINavigationController, viewWillAppear was called but not when pushed in the second navigation controller.

Then I came across this post UINavigationController should call viewWillAppear/viewWillDisappear methods

And realized that my second navigation controller did redefine viewWillAppear. Screening the code showed that I was not calling

[super viewWillAppear:animated];

I added it and it worked !

The documentation says:

If you override this method, you must call super at some point in your implementation.

Antoine
A: 

I think what they mean "directly" is by hooking things up just the same way as the xcode "Navigation Application" template does, which sets the UINavigationController as the sole subview of the application's UIWindow.

Using that template is the only way I've been able to get the Will/Did/Appear/Disappear methods called on the object ViewControllers upon push/pops of those controllers in the UINavigationController. None of the other solutions in the answers here worked for me, including implementing them in the RootController and passing them through to the (child) NavigationController. Those functions (will/did/appear/disappear) were only called in my RootController upon showing/hiding the top-level VCs, my "login" and navigationVCs, not the sub-VCs in the navigation controller, so I had no opportunity to "pass them through" to the Nav VC.

I ended up using the UINavigationController's delegate functionality to look for the particular transitions that required follow-up functionality in my app, and that works, but it requires a bit more work in order to get both the disappear and appear functionality "simulated".

Also it's a matter of principle to get it to work after banging my head against this problem for hours today. Any working code snippets using a custom RootController and a child navigation VC would be much appreciated.

Bogatyr