Alex Stone
Alex Stone

Reputation: 47338

iOS5 how to "lazily" initialize controllers for the tab bar?

I have a TabBar controller with up to 9 controllers, each one has a navigation controller. Currently, I alloc and init each one of them within the app delegate in the

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{...}

This makes my app take quite some time to start when first started. I'd like to reduce the initial loading time with lazy initialization.

Is there a way to "lazily" init view controllers when they are first selected for the tab bar?

Will looking into storyboards for iOS5 help me with this issue?

Thank you!

Upvotes: 3

Views: 923

Answers (3)

XJones
XJones

Reputation: 21967

Felt like adding a quick .02 to this question. The UIViewController initialization and loading process is already "lazy" as others have pointed out. The real question is what are you doing in your initialization that is taking so long? Even loading views shouldn't take a long time as you don't want users to wait when the tap a tab before the view changes. I suggest the following:

  1. In init, do as little as possible. The purpose of init is to have whatever view independent data initialized and ready. You should not be loading any views here.

  2. In loadView or viewDidLoad create all your views/subviews.

  3. Only load data when you need it. If you need it in init, load it there. If you can wait until the views are loaded, do it in viewDidLoad. If loading data takes any significant time, load it in the background.

Upvotes: 2

sergio
sergio

Reputation: 69027

What about defining your controllers as lazy controllers?

I mean, if the app takes some time to start due to initialization of nine view controllers, then this has to do with what the controller actually do at init time. So, you could make the controller lazily init in two steps: one, when you add all of your controllers to the tab bar controller; two, when you select a specific tab, then the corresponding controller gets initialized.

I think this is the cleanest approach.

Otherwise, I would bet on directly using UITabBar to manage it in your own tab bar controller class.

As a last option, I would try and change on the fly the content of the tab bar controller by calling setViewControllers:animated: at appropriate times according to some logics. For example, you could initialize the tab bar controller with only 5 view controllers in application:didFinishLaunchingWithOptions:, then add the rest at a later moment...

But my actual suggestion is making the component controllers lazy...

EDIT: after reading your question in the comment...

if you would give a try to lazy initialization of your controllers, what I mean is following:

  1. you will initialize your controllers (or UIKit will when loading the nib) by calling [[... alloc] init...]; this is not changing;

  2. the init method will initialize the controller to its default state, like setting properties and ivar values, and do nothing more complex;

  3. before the controller view gets displayed, you complete its initialization by calling a specific method; this would carry through the "quite a lot of delegation" part, which I assume to be the lengthy part of initialization.

Sorry if talking about "lazy initialization" caused an ambiguity between the logical initialization of the component and the content of the initmethod.

As to point 3, you have several options about where to complete the initialization.

On possibility is when the controller is about to be displayed. In this case, either you define -tabBarController:didSelectViewController: in the tab bar controller delegate, or you use viewWillAppear. This will give you the laziest initialization of all, but it could be add some delay on the exact moment when you select the tab before the view appears.

Better yet is using viewDidLoad, which would give you a kind of less lazy initialization; the initialization of all your controllers would happen at some point in time that you do not control (of course, before the view is displayed), so it might delay things a bit, but it would not happen in applicationDidFinishLoading and would be more UI-friendly since it would be controlled by the main loop. Definitely, the first option to try. Give also a look at the description of viewDidLoad in the UIViewController reference.

Finally a note about the separate thread. Keep in mind that is not all safe using UIKit from a separate thread, so be careful.

Upvotes: 3

JeanLuc
JeanLuc

Reputation: 4903

In your implementation of UIViewController create all your Views in the method

- (void)viewDidLoad

and avoid creating views (or even worse acquire data) in your init Method.

An UITabBarController or an UINavigationController will call the viewDidLoad by default lazy i.e. right before the user sees it.

Upvotes: 1

Related Questions