UITabBarController setting selected index on launch causing issues

I have 5 tabs and on applicationWillTerminate the currently selected index is archived for use on the next launch. I am having some issues with setting the selected index when the application launches the next time. It seems that if I use the following it works, albeit quite hackishly (it displays tab 1 for a split second then goes to the proper tab):


[self performSelector:@selector(selectSavedTabBarIndex) withObject:nil afterDelay:0.0];


If I do either of the following it works great on the simulator but locks up the device requiring pressing the power button and waiting 10 seconds to close the app. There are no errors/crashlogs of the event when hooked up to a debugger.

[self selectSavedTabBarIndex];

// Add the tab bar controller's current view as a subview of the window
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];



// Add the tab bar controller's current view as a subview of the window
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
[self selectSavedTabBarIndex];


Does anyone have any ideas why this would occur? Could it be an Apple bug?

iMac, Mac OS X (10.5.4)

Posted on Sep 17, 2008 9:45 AM

Reply
12 replies

Sep 17, 2008 10:58 AM in response to uprise78

The call to:


[window addSubview:tabBarController.view]


is the first time the view is actually created. So trying to set any state before that will be bad.

What I do is instantiate the view controller, pass it state information (which just holds onto the data), and then add the view as normal.

The trick here is that the view controller doesn't make use of the state information until the its 'viewDidLoad' method. It is here that it is safe to set previous state. This works whether you use IB or whether you are progmatically creating all of your controls (in 'viewDidLoad').

The reason your approach works on the simulator but not the device is most likely because the simulator is so much faster. By the time your 2nd approach (setting state after adding the subview) is run, the view has already been loaded. But on a device, it hasn't fully loaded yet so it crashes.

Sep 17, 2008 11:30 AM in response to RickMaddy

I tried sub classing UITabBarController and overriding viewDidLoad with something like this:

- (void)viewDidLoad
{
[super viewDidLoad];

self.selectedIndex = appDelegate.userSettingsObject.tabBarLastSelectedIndex;
}


Oddly enough, I got the same result. No crash logs. The tab was properly selected but the app was non responsive. I also tried overriding viewWillAppear: and viewDidAppear: to see if that made a difference but for some reason they all have the same result.

It always works with the display glitch when using the following (correct me if I'm wrong, but using a delay of 0 just makes the selector get called on the next iteration of the main run loop). Very odd.

[self performSelector:@selector(selectSavedTabBarIndex) withObject:nil afterDelay:0];


Any other ideas?

Sep 17, 2008 11:51 AM in response to uprise78

Maybe i'm not understanding something the problem. The app i'm working on has a tab bar controller, so it was pretty easy for me to select which tab view is shown initially like this:

- (void)applicationDidFinishLaunching:(UIApplication *)application {           self.playNetwork = [[NSUserDefaults standardUserDefaults] stringForKey:@"network_mode_preference"];      self.user = [[NSUserDefaults standardUserDefaults] stringForKey:@"user"];            // Create the navigation and view controllers            [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque];        MZAppDelegate *appDelegate = (MZAppDelegate *)[[UIApplication sharedApplication] delegate];     appDelegate.channelList = [NSMutableArray array];     appDelegate.contentList = [NSMutableArray array];      appDelegate.messagesList = [NSMutableArray array];            UITabBarController *aTabBarController = [[UITabBarController alloc] init];      firstViewController = [[FirstViewController alloc] init];      secondViewController = [[SecondViewController alloc] init];      thirdViewController = [[ThirdViewController alloc] init];      fourthViewController = [[FourthViewController alloc] init];      fifthViewController = [[FifthViewController alloc] init];      aTabBarController.delegate = self;            self.tabBarController = aTabBarController;            NSArray *tabViewControllers = [[NSArray alloc] initWithObjects:firstViewController,                                                                                    secondViewController,                                                                                    thirdViewController,                                                                                    fourthViewController,                                                                                    fifthViewController,                                                                                    nil];            [tabBarController setViewControllers: tabViewControllers animated:YES];      tabBarController.selectedIndex = 4;            [tabBarController release];      [tabViewControllers release];            [firstViewController release];      [secondViewController release];      [thirdViewController release];      [fourthViewController release];      [fifthViewController release];            // Configure and show the window           [window addSubview:[tabBarController view]]; }  


... is this not what you're also trying to do?

Regards,

John

Falling You - exploring the beauty of voice and sound
http://www.fallingyou.com

Sep 17, 2008 12:33 PM in response to jmzorko

@RickMaddy

viewDidLoad doesn't get called for view controllers that are in a UITabBarController on a tab that isn't the selected tab. For example, if tab 4 was my last selected tab and I am loading my UITabBarController and all of it's subViews from a nib, the viewDidLoad wont get called on tab 4 until tab 4 is touched. I tried awakeFromNib which did get called but it had the same frozen result.

@jmzorko

Creating the view controllers in code (as opposed to from a nib) as you did worked as planned. I have a little bit of refactoring to do but at least it works.

Thanks to all who posted.

Oct 1, 2008 2:20 PM in response to Ostrowsky S

It turns out the bug was from a UITableView that was in the first tab. For some reason beyond my comprehension, if I set the rowHeight for the tableview in awakeFromNib it worked but if it was in init: it would crash if the selectedIndex was anything other than 0. Both pieces of code got hit but it wouldn't function until I deleted the setting of rowHeight from init:. Very odd indeed.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

UITabBarController setting selected index on launch causing issues

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.