Tab bar controller inside a navigation controller,

2018-12-31 21:47发布

I'm trying to implement a UI structured like in the Tweetie app, which behaves as so: the top-level view controller seems to be a navigation controller, whose root view is an "Accounts" table view. If you click on any account, it goes to the second level, which has a tab bar across the bottom. Each tab item shows a different list and lets you drill down further (the subsequent levels don't show the tab bar).

So, this seems like the implementation hierarchy is:

  • UINavigationController
    1. Accounts: UITableViewController
    2. UITabBarController
      1. Tweets: UITableViewController
        • Detail view of a tweet/user/etc
      2. Replies: UITableViewController
      3. ...

This seems to work[^1], but appears to be unsupported according to the SDK documentation for -pushViewController:animated: (emphasis added):

viewController: The view controller that is pushed onto the stack. It cannot be an instance of tab bar controller.

I would like to avoid private APIs and the like, but I'm not sure why this usage is explicitly prohibited even when it seems to work fine. Anyone know the reason?

I've thought about putting the tab bar controller as the main controller, with each of the tabs containing separate navigation controllers. The problem with this is that each nav controller needs to share a single root view controller (namely the "Accounts" table in Tweetie) -- this doesn't seem to work: pushing the table controller to a second nav controller seems to remove it from the first. Not to mention all the book-keeping when selecting a different account would probably be a pain.

How should I implement this the Right Way?

[^1]: The tab bar controller needs to be subclassed so that the tab bar controller's navigation item at that level stays in sync with the selected tab's navigation item, and the individual tab's table controller's need to push their respective detail views to self.tabBarController.navigationController instead of self.navigationController.

9条回答
爱死公子算了
2楼-- · 2018-12-31 21:48

The two previous answers got it right - I don't use UITabBarController in Tweetie. It's pretty easy to write a custom XXTabBarController (plain subclass of UIViewController) that is happy to get pushed onto a nav controller stack, but still lives by the "view controller" philosophy. Each "tab" on the account-specific view (Tweets/Replies/Messages) is its own view controller, and as far as they are concerned they're getting swapped around on screen by a plain-ol UITabBarController.

查看更多
看淡一切
3楼-- · 2018-12-31 21:48

I'm building an app that uses a similar navigation framework to Tweetie. I've written a post about how to do this on my blog www.wiredbob.com which also links to the source code. It's a full template you could take and use as a basis for another project. Good luck!

查看更多
零度萤火
4楼-- · 2018-12-31 21:51

This could be achieved by simply embedding the TabBarController in the Navigation Controller. In the storyboard:

  1. Drag a ViewController
  2. Click on the ViewController's Scene
  3. Click on editor >> Embed in >> Navigation Controller.
  4. Drag a button on the same ViewController.
  5. Drag a TabBarController
  6. Connect the button on the ViewController to the TabBarController via push Segue Action.

In this case only the TabBarController's RootViewController would be in the Navigation Controller's stack. All The TabBarItems would have the Navigation Bar at the top and user can go to Home Screen at any time, irrespective of the selected TabBarItem

This could be done at any ViewController in the Navigation Controller's stack.

If it works, please suggest me how to increase the reputation so that I can post the images and the code in the next answer. :)

查看更多
长期被迫恋爱
5楼-- · 2018-12-31 21:58

I was struggling for the past hour to implement a UITabBar because it would get hidden when I tried to display my view; then I found this post:

Basically, make sure you insert your new view below the tabbar, per this line of code:

[self.view insertSubview:tab2ViewController.view belowSubview:myTabBar];
查看更多
十年一品温如言
6楼-- · 2018-12-31 22:01

I do this in a couple of my apps. The trick to adding a tab bar to a navigationController based app is to NOT use a TabBarController. Add a Tab Bar to the view, make the view controller for that view a TabBarDelegate, and respond to user selections on the tab bar in the code of the view controller.

I use Tab Bars to add additional views to the Tab Bar's view as sub-views, to reload a table view with different datasets, to reload a UIPickerView, etc.

查看更多
谁念西风独自凉
7楼-- · 2018-12-31 22:01

This is how i did it. This is actually pushing a tabbarcontroller onto navigation controller. It works fine. I didn't find anywhere in the documentation that apple doesn't support this way. Can someone give me link to this warning?

If this is truth, is it possible that apple refuses to publish my app to appstore?

-(void)setArrayAndPushNextController
{
    MyFirstViewController *myFirstViewController = [[MyFirstViewController alloc] init];
    MySecondViewController *mySecondViewController = [[MySecondViewController alloc] init];

    myFirstViewController.array = self.array;


    NSArray *array = [[NSArray alloc] initWithObjects:myFirstViewController, mySecondViewController, nil];
    UITabBarController *tab = [[UITabBarController alloc] init];
    tab.viewControllers = array;

    [array release];

    UITabBarItem *item1 = [[UITabBarItem alloc] initWithTitle:@"first title" image:nil tag:1];
    UITabBarItem *item2 = [[UITabBarItem alloc] initWithTitle:@"second title" image:nil tag:2];

    myFirstViewController.tabBarItem = item1;
    mySecondViewController.tabBarItem = item2;

    [self stopAnimatingSpinner];

    [self.navigationController pushViewController:tab animated:YES];

    [tab release];
    [item1 release];
    [item2 release];
}
查看更多
登录 后发表回答