Make a view (initialized from initWithNibName) loa

2020-02-04 20:58发布

问题:

Assuming I load a view controller from a nib, and decide to do something with one of its subview behind the scene. At a later moment in time, I would show the view of this view controller.

viewController = [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil]; 
[viewController.someSubview doSomething];

//later on 
[mainView addSubview:viewController.view];

The problem is that, the someSubview object doesn't seem to be loaded until the view appears, so the method doSomething is not called. So far my workaround is to call:

[mainView addSubview:viewController.view];
[viewController.view removeFromSuperview];

to initialize the subviews of viewcontroller first. Is there any more elegant way (like a loadSubviews method or something) for this task?

回答1:

First of all I would try simply accessing the property:

[viewController view];

This will force the lazy load of the view (and thus the subviews and outlets etc.) and this might be enough for you. View controllers by default will not load their view until you access it so this might be why you are seeing a delay.

Forcing a load like this is usually the solution when you are trying to access an outlet property but it hasn't actually been bound yet, like someSubview in your case.

You can also improve things a bit by adding the view but making it hidden:

viewController.view.hidden = YES;
[mainView addSubview:viewController.view];

Then instead of calling addSubview when you want to show it, just do:

viewController.view.hidden = NO;

I've used this method when animating in views using the UIViewAnimationTransitionFlipFromRight etc. transitions. Even when forcing a lazy load of the view there is still a noticable lag, so I've used this to improve the performance a bit.



回答2:

iOS 9 introduced -(void) loadViewIfNeeded

I use

if ([_myVC respondsToSelector:@selector(loadViewIfNeeded)]) {
    [_myVC loadViewIfNeeded];
} else {
    [_myVC view];
}