views:

163

answers:

2

I'm loading a view like this:

if(commentSubmissionView == nil){
    commentSubmissionView = [[CommentSubmissionController alloc] initWithNibName:@"CommentSubmissionView" bundle:nil];  
}
[self.view addSubview:commentSubmissionView.view];

viewDidLoad and viewWillAppear in commentSubmissionView do not fire. Is there something else I need to do?

+1  A: 

If you're using addSubview: then you also need to use bringSubviewToFront: as follows:

if(commentSubmissionView == nil){
    commentSubmissionView = [[CommentSubmissionController alloc] initWithNibName:@"CommentSubmissionView" bundle:nil];  
}
[self.view addSubview:commentSubmissionView.view];
[self.view bringSubviewToFront:commentSubmissionView.view];
h4xxr
That will throw this exception:'NSInvalidArgumentException', reason: '*** -[UIView makeKeyAndVisible]: unrecognized selector sent to instance 0x352550'
4thSpace
Sorry, answered too hastily. Now corrected...
h4xxr
You can also call viewDidLoad and friends explicitly though that brings with it the risk of you forgetting about it and having them called weirdly in the future.
toholio
@h4xxr:viewDidLoad does fire now but not viewWillAppear. Do you know why?
4thSpace
+1  A: 

The documentation for viewWillAppear: isn't completely clear but have a look at what it says:

This method is called in response to a view being added either directly or indirectly to a window. You add views to a window directly by using the addSubview: method to add them to the window’s view hierarchy. You can also add a view indirectly in several ways, including by pushing it onto a navigation stack or by presenting it modally (using the presentModalViewController:animated: method). This method is called before the view is actually added to the window and before any animations are configured.

The viewDidAppear: and viewWillAppear: methods will only be called if you are:

  1. Adding them to a window (adding to a view does not count -- it must be a window)
  2. Using pushViewController: or presentModalViewController:animated: or switching tabs in a tab controller or any other situation where an Apple-provided view controller adds the view controller and its view for you.

In the situation you have, where you are adding a view to another view, you must invoke viewWillAppear: and viewDidAppear: on the view controller yourself or they won't happen.

I don't know why viewDidLoad was not getting invoked for you initially. It will always be invoked after loadView, when the view property accessor is invoked on the controller for the first time, unless an error occurs. It is possible the view load was failing (you'd have to check the console log).

You do not need to follow addSubview: with bringSubviewToFront: since addSubview: always adds to the front. Again, from the documentation of addSubview:

Adds a view to the receiver’s subviews so it’s displayed above its siblings.

Matt Gallagher
Thanks. In #1, you say "...adding to a view does not count..." Yet the documentation states, "You add views to a window directly by using the addSubview: method...". Since I am using addSubview, the method should fire correct?
4thSpace
addSubview: only causes viewDidAppear: and viewWillAppear: to fire if you invoke addSubview: on a window (i.e. [window addSubview:newView]). Since you are invoking it on a view (i.e. [view addSubview:newView]), it won't work. I don't know why Apple have made this distinction but they have.
Matt Gallagher