Do I programmatically add SubViews in ViewDidAppear, ViewDidLoad, ViewWillAppear, the constructor?
Asked Answered
E

3

25

I'm trying to figure out from Apple's sketchy documentation which method is the best place to be initializing and adding my Views controls to the controller's view.

With winforms it's fairly straightforward, as they're always initialized inside InitializeDesigner, called in the constructor. I'm trying to match the reliability of this pattern if possible.

I'm working with UIViewControllers and UITableViewControllers inside a UINavigationController most of the time - if this effects it all.

Here's an example:

public MyController()
{
    // Here?
    AddViews();
}

public override ViewDidLoad()
{
    base.ViewDidLoad();

    // Or is should it be here?
    AddViews();
}

public override ViewWillAppear(bool )
{
    base.ViewWillAppear(animated);

    // Here?
    AddViews();
}

public override ViewDidAppear(bool animated)
{
    base.ViewDidLoad(animated);

    // Or maybe here?
    AddViews();
}

void AddViews()
{
    UILabel label = new UILabel();
    label.Text = "Test";
    label.Frame = new RectangleF(100,100,100,26);
    View.AddSubView(label);

    UIWebView webview = new UIWebView();
    webview .Frame = new RectangleF(100,100,100,26);
    View.AddSubView(webview);
}

I get mixed results with some UIControls when I add them to the view in different places. Visual lag sometimes, othertimes the webview is hidden somewhere.

Is there a general rule to keep to for adding them?

Eme answered 17/2, 2010 at 12:11 Comment(1)
See also: #574458Eme
M
73

In general, this is what I do:

  • ViewDidLoad - Whenever I'm adding controls to a view that should appear together with the view, right away, I put it in the ViewDidLoad method. Basically this method is called whenever the view was loaded into memory. So for example, if my view is a form with 3 labels, I would add the labels here; the view will never exist without those forms.

  • ViewWillAppear: I use ViewWillAppear usually just to update the data on the form. So, for the example above, I would use this to actually load the data from my domain into the form. Creation of UIViews is fairly expensive, and you should avoid as much as possible doing that on the ViewWillAppear method, becuase when this gets called, it means that the iPhone is already ready to show the UIView to the user, and anything heavy you do here will impact performance in a very visible manner (like animations being delayed, etc).

  • ViewDidAppear: Finally, I use the ViewDidAppear to start off new threads to things that would take a long time to execute, like for example doing a webservice call to get extra data for the form above.The good thing is that because the view already exists and is being displayed to the user, you can show a nice "Waiting" message to the user while you get the data.

There are other tricks you can use, though. Lets say you want a UILabel to "fly" into the form after the form is loaded. In that case, I would add the label to the form in the ViewDidLoad but with a Frame outside of the view area, and then in the ViewDidAppear I would do the animation to fly it back into view.

Hope it helps.

Malayoindonesian answered 17/2, 2010 at 14:46 Comment(3)
Thanks that's cleared a lot up. I haven't been able to add anything with the LoadView example from this question: #574458 - do you ever use this method?Eme
So basically loadView is a method from the UIViewController (Use the rosetta stone when you're trying to figure these things out - tirania.org/tmp/rosetta.html). The framework automatically calls this method in the controller to tell it to create views, and the default implementation of the UIViewController then calls the ViewDidLoad. Although you can override this method (and make sure you call the base method when you do), personally, I prefer to to just use the viewWillLoad (called before loadView) and viewDidLoad (called just after).Malayoindonesian
I disagree you should not call it; it depends on the behavior you want. If you're inheriting a ViewController and want to use the view created by the parent, then yes, you need to explicitly call super.loadView. It depends on the case, but what you don't want to happen is let your superclass create the view, then throw it away on your overload.Malayoindonesian
G
9

Hmm, Apple's docs seem to be pretty clear, IMHO.

If you create your own root view (the root view of this particular controller's view hierarchy) programmatically, you should create it in -loadView without calling super and set the view property when done. If your view is loaded from a nib, you should not touch -loadView.

You add custom subviews to the view controller's view or otherwise modify it in -viewDidLoad. The recommended practice is to create your UILabel and UIWebView in -viewDidLoad and release them in -viewDidUnload, setting their references to nil if you need to keep them in ivars.

Note: -viewDidUnload is deprecated in iOS 6 and is just not called any more, because UIViewController no longer purges its view under memory pressure.

Generate answered 17/2, 2010 at 12:45 Comment(4)
Thanks I missed that method. However I still feel the methods I listed give very limited info of when to use them. Even in loadView all you're told is 'If you want to perform any additional initialization of your views, do so in the viewDidLoad method' - when would you ever need this method?Eme
loadView is the method which either loads the view hierarchy from NIB or just creates an empty UIView if there's no NIB to load. You may want a custom view instead of it, in which case you override loadView. UITableViewController, for example, overrides this method to create a UITableView. I often find myself doing the same thing with my own UIView subclasses.Generate
viewDidUnload is deprecatedNones
@SargeBorsch Yep, the answer is too old. Thanks, I updated this bit.Generate
M
2

viewDidLoad relates to 'MEMORY', and viewWillAppear/viewDidAppear relates to 'APPEARANCE'. A view controller's view (which is a root-view of your view controller's views) can appear/disappear numerous times, even if the controller's view is already in memory.

(When referring to root-view, I also means its subviews, because the root-view has reference to its children (subviews), but from a view controller's perspective, it usually knows just the root-view. Reference to subviews can happens normally through view controller's outlets.)

The root-view itself MAY be removed from memory when there's a memory warning. The view controller will determine when is the best time to removed them from memory.

So, you would normally add subviews in viewDidLoad, because adding subviews means adding them to memory. BUT not if you create all of your views programmatically (not from a nib files). If that's the case then you should override loadView method, and create a root-view and add subviews there, so in this case you can omit viewDidLoad to add subviews.

Melidamelilot answered 5/1, 2012 at 12:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.