I have a UITabBarController
with two tabs. Each tab is a UITableViewController
.
When the UITabBarController
appears, the two tab views each have incorrect bounds. The first tab sits correctly under the navigation bar, but extends below the tab bar at the bottom. The second tab is the other way around, starting underneath the navigation bar but stopping correctly before the tab bar at the bottom.
I'm creating and presenting the TabBarController as follows:
ActiveListTabBarViewController* listTabBarController = [[ActiveListTabBarViewController alloc] initWithListController:_listController];
UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController:listTabBarController];
[self presentViewController:nc animated:YES completion:^(){}];
And then in the init
for the TabBarController, creating and adding the child (tab) views as follows:
_todoListViewController = [[BasicTableViewController alloc] initWithList:[_controller itemsToDo]];
_todoListViewController.delegate = self;
_todoListViewController.title = @"To Do";
_completedListViewController = [[BasicTableViewController alloc] initWithList:[_controller itemsDone]];
_completedListViewController.delegate = self;
_completedListViewController.title = @"Completed";
[self setViewControllers:@[_todoListViewController, _completedListViewController]];
What am I doing wrong?
Thanks, Gavin
Update: following the suggestion to add the following method to BasicTableViewController
:
- (UIRectEdge)edgesForExtendedLayout
{
return UIRectEdgeNone;
}
The behaviour of the first tab has improved and is positioned correctly, but the second tab remains the same. Situation now as follows:
Any suggestions? Cheers.
The problem was caused by the way in which I was presenting the UITabBarController
ActiveListTabBarViewController* listTabBarController = [[ActiveListTabBarViewController alloc] initWithListController:_listController];
UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController:listTabBarController];
[self presentViewController:nc animated:YES completion:^(){}];
Returning to Apple's docs, I wasn't sure if this was a valid way to present a UITabBarController
. That is, presenting it as the child of another view controller.
It's not. Following are some snippets that confirmed it for me; from this, and the resulting change, I'm assuming it's not correct to present a TabBarController as I have, above.
From: https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/TabBarControllers.html
Before creating a tab bar interface, you need to decide how you intend to use a tab bar interface. Because it imposes an overarching organization on your data,you should use one only in these specific ways:
- Install it directly as a window’s root view controller.
- Install it as one of the two view controllers in a split view interface. (iPad only)
- Present it modally from another view controller.
- Display it from a popover. (iPad only)
From: https://developer.apple.com/library/ios/documentation/uikit/reference/UITabBarController_Class/Reference/Reference.html
Unlike other view controllers, a tab bar interface should never be installed as a child of another view controller.
And further clarification:
A tab bar controller is a container view controller that you use to divide your app into two or more distinct modes of operation.
A navigation controller presents data that is organized hierarchically and is an instance of the UINavigationController class. The methods of this class provide support for managing a stack-based collection of content view controllers.
The reason I presented the UITabBarController
as the root view of a navigation controller, is that I wanted the navigation bar...
This is how I'm achieving that now, inside the init for the TabBarController:
- (id)initWithListController:(BasicListController *)controller
{
self = [super init];
if (self) {
_controller = controller;
_todoListViewController = [[BasicTableViewController alloc] initWithList:[_controller itemsToDo]];
_todoListViewController.delegate = self;
_todoListViewController.title = @"To Do";
_completedListViewController = [[BasicTableViewController alloc] initWithList:[_controller itemsDone]];
_completedListViewController.delegate = self;
_completedListViewController.title = @"Completed";
UINavigationController* ncTodo = [[UINavigationController alloc] initWithRootViewController:_todoListViewController];
UINavigationController* ncCompleted = [[UINavigationController alloc] initWithRootViewController:_completedListViewController];
[self setViewControllers:@[ncTodo, ncCompleted]];
UIBarButtonItem* doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStylePlain target:self action:@selector(doneTap:)];
_todoListViewController.navigationItem.leftBarButtonItem = doneButton;
_completedListViewController.navigationItem.leftBarButtonItem = doneButton;
}
return self;
}
Note, I didn't have to do anything with:
The iOS 7 defaults respect the navigation bar and the tab bar (unlike the original screen shots above, when the UITabBarController
was presented incorrectly).
try implementing this method in your view controller:
- (UIRectEdge) edgesForExtendedLayout
{
return UIRectEdgeNone;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With