1
votes

In my iOS app I'm creating and presenting a UINavigationController modally like so:

MyViewController *myvc = [[[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil] autorelease];
UINavigationController *navVC = [[[UINavigationController alloc] initWithRootViewController:myvc] autorelease];
[self presentModalViewController:navVC animated:YES];

In the MyViewController viewDidLoad I'm creating and setting toolbar items for the navigation controller's toolbar, like so:

self.navigationController.toolbar.items = [NSArray arrayWithObjects:(items...), nil];

the problem I'm having is that the items don't show up. If instead I call a method from MyViewController's viewDidLoad method that adds the toolbar items via performSelector:withObject:afterDelay:0, then it works perfectly. So there's obviously some race condition going on here with the initial presentation of the UINavigationController, initialization of its toolbar/navbar, and the initialization of the nav bar's specified initial root view controller.

I verified in the debugger that the root view controller's viewDidLoad is called after the UINavigationController's viewDidLoad method. In fact, the root view controller's viewDidLoad method is not called until presentModalViewController: is called, and the UINavigationController's viewDidLoad is called within initWithRootViewController, so doesn't that imply that the UINavigationController object should be "all ready to go", including its nav bar and toolbars?

I thought at first that the navigation controller's toolbar object may not exist yet at MyViewController's viewDidLoad time, but it clearly does. At least, NSLog shows that it is not nil during MyViewController's viewDidLoad method. In fact, the UINavigationController's toolbar object is identical at both times: in the root view controller's viewDidLoad, and in the "setupToolbar" method that I called with performSelector:withObject:afterDelay, so it's not getting "re-initialized" somehow.

So, what's going on here? Why aren't my toolbar modifications "sticking" in MyViewController's viewDidLoad, and why does performing them in the next iteration of the runloop (performSelector:withObject:afterDelay:0) make it work?

What is the "right" way of setting up initial navbar / toolbar items in code from the rootViewController of the UINavigationController?

Edit: well I figured out "what" is happening, although I still don't understand the "why": after MyViewController's viewDidLoad method returns (where I have verified that the navigation controller's toolbar's items array is non-nil) and sometime before/in the next runloop iteration (or whenever a performSelector:withObject:afterDelay:0 is called), the items property of the navigation controller's toolbar is set to nil!

Edit: same problem when calling [self.navigationController setToolbarItems:animated:]

Edit: solved, the right way is [self setToolbarItems:animated:], not [self.navigationController setToolbarItems:animated:], thanks!

1

1 Answers

2
votes

Just a guess here, but have you tried using

[self setToolbarItems:[NSArray arrayWithObjects:(items...), nil] animated:NO];

from within MyViewController's viewDidLoad method? I'm not sure if it's the correct way to directly access the navigation controller's toolbar like you did. At least the API states

UIViewController Class Reference

...

- (void)setToolbarItems:(NSArray *)toolbarItems animated:(BOOL)animated

...

View controllers that are managed by a navigation controller can use this method to specify toolbar items for the navigation controller’s built-in toolbar. You can set the toolbar items for your view controller before your view controller is displayed or after it is already visible.