I have an application created from the tabbed application template. (ARC, iOS 4)
Problem
Now, when ModalViewCont on screen, pressing the Home button to put application in background and after getting the application back, closing the ModalViewCont does not bring back the ViewCont2's view but a black screen with the tabbar at the bottom. The same thing happens without putting the application background/foreground; if other tabs tapped before tapping the 2. tab.(EDIT : This happens only if self.view set to nil in viewWillDisappear instead of viewDidDisappear.)
I determined that ViewCont2 loads a new view (checked it's reference) but view's superview is nil so the new view is not displayed but a black screen.
Things that did not work
Solutions i considered;
_
if (self.view.superview == nil)
{
self.tabBarController.selectedViewController = nil;
self.tabBarController.selectedViewController = self;
}
Questions
EDIT : It seems that when viewDidLoad is called earlier than it should(i.e when view nilled in viewWillDisappear instead of viewDidDisappear), superview is not set.
It seems weird, but your suggestion (1) is indeed a correct workaround for this problem:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!self.view.superview) { // check if view has been added to view hierarchy
self.tabBarController.selectedViewController = nil;
self.tabBarController.selectedViewController = self;
}
}
Your second suggestion is good for performance (because view loading is an expensive operation) - but it will not solve the problem. You can also end up with a black screen without setting the view to nil in the following situation (test this in the iOS simulator):
Generally you can assume that in viewDidLoad the view property is set and in viewWillAppear + viewDidAppear the view has been added to the view hierarchy; so the superview should be there at that time (Here the superview is a private view of the tabbarcontroller of class UIViewControllerWrapperView). However in our case, although the view is reloaded (at the time of app resume), it is not added to the view hierarchy resulting in a black screen. This seems to be a bug in UITabBarController.
The workaround forces the appearance selectors to be performed again. So viewWillAppear will be called again, this time with a superview in place. Also viewDidAppear will be called twice!
Setting self.view to nil is okay, but should not be necessary in most cases. Let the system decide when to unload the view (iOS can unload views when memory gets low). The view controller code should be designed in a way so that the UI can be reconfigured at any time without reloading the view.