add a view under tabbar in storyboard - ios

I'm wondering if there's a way (preferably an easy one) to add a view under the tab bar, like shown on the attached picture, so that it stays there when I switch between tabs and when new view controllers are pushed/popped on each tab.
I have subclassed UITabBarController as "MainTabController" and set is as the custom class for the Main Tab Bar Controller Scene in my storyboard. Then in MainTabController's viewDidLoad I move the tabBar up and add the red subview. So far so good, but the main view area size is still like it was before, with the tab bar at the bottom, so now the last few elements of the table stay below the tab bar.
I would very much like to avoid adjusting the frame size for each and every controller I push into either of the tabs, so I hope that there's a simpler solution that I'm not aware of.

You can do this by embedding your tab bar controller in a custom container controller. You can do this in a storyboard by making a UIViewController the initial view controller, and adding a container view to it. Size that container view so it has whatever space you need underneath, and add your view in that space. Delete the view controller that comes automatically embedded in the container view, and control drag from the container view to your tab bar controller, and choose "embed".
Be aware that there's a bug in the way tab bar controllers layout their views in iOS 7. If you put a view near the bottom of one of the controllers, it will appear the first time you see it, but move down under the tab bar when you select another tab and then come back again (it will reappear if you rotate to landscape and then back again). You can get around this bug by making your container view controller (the initial controller in my storyboard) the delegate of the tab bar controller, and adding this code.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // called by the embed segue
UITabBarController *tbc = segue.destinationViewController;
tbc.delegate = self;
}
-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
[tabBarController.view setNeedsLayout];
}

Related

Why does embedding a View Controller in a Navigation Controller, then in a Tab Bar Controller attach the nav bar to the Tab Bar Controller?

Back when I first created the foundational layout for the app I'm currently working on in Storyboard, I did it in two steps:
Selected my View Controller and used Editor->Embed In->Navigation Controller.
Selected my View Controller again and used Editor->Embed In->Tab Bar Controller.
This was the resulting layout:
Question 1: Why do these steps create such an odd layout?
In this weird layout that seems to imply that the Navigation Controller is attached to the Tab Bar Controller as its parent, the only way I can get navigation items to display in the app (in the view controlled by the View Controller on the right) is by placing them in the nav bar of the Tab Bar Controller scene.
However, this creates various issues, including not being able to create an IBOutlet in my View Controller file for a custom view I drag into the title view slot in the Tab Bar Controller scene. Meanwhile, dragging anything into the navigation bar in the View Controller scene just makes it not appear in the app when it runs.
Question 2: How can I fix this layout so that I can control-drag from navigation items into my View Controller file? Or is everything actually correct, and I'm just trying to force something I shouldn't? (My intention here is to be able to set the custom title view's text in my View Controller code.)
Its obvious, if you want to embed MyViewController to NavigationController then you need to change your second step and need to embed NavigationController to Tab Bar Controller.
Selected MyViewController and used Editor->Embed In->Navigation Controller.
Selected NavigationController Embed with MyViewController and used Editor->Embed In->Tab Bar Controller.
It should look like this.
Note: You need to embed MyViewController to navigationController only if you want to perform push operation on this TabBarItem means with MyViewController other wise simply embed MyViewController to TabBarController no need to embed it with NavigationController.

Fake UINavigation Bar

I'm making an app in Swift and even though i'm using a navigation controller, there is a particular point where I want to present a view controller rather than make a segue and have the viewController added to the navigation stack.
This view controller i'm presenting is completely disconnected from the rest of the storyboard (it gets reused by a few screens).
To "fake" that it's part of the navigation controller stack, I wanted to drag and drop a navigation bar onto this orphaned view controller, and then manually add a back button. I want to handle my own back functionality and then use self.dismissViewControllerAnimated(true, completion: nil) to go back.
The problem is that this navigation bar doesn't have the same height or feel as the traditional one - the back button is way up high almost hitting the carrier/bars of service/4g/LTE area, and the title is touching the top of the screen. It's too high.
If I manually move it down, it's height doesn't occupy the whole area and there is this weird white strip.
Any ideas on how I can drag&drop my own navigation bar and get it to look like the ones typically done when you have a navigation controller?
Thanks!
Can you wrap your controller in a navigation controller, and present the nav controller modally:
UINavigationController *modalNavcontroller = [[UINavigationController alloc] initWithRootViewController:youController];
[self presentViewController:mdalNavcontroller animated:YES completion:nil];

going back inside navigation controller through embedded view controller

In my iOS project I have a main menu that is shown embedded in a container in my initial UIViewController.
After the user choses any row in that menu, the navigation controller pushes the submenu viewController that manages further actions, which uses the full window.
If the user wants to go back to main screen, he taps "back" button and my navigationController pops back. But when it should pop to the main viewController it fails to restore the view of my initial viewController.
Do you have any clue how to pop back to the first viewController in navigationViewController hierarchy if that view controller has containers with embedded view controllers in them?
Or should I consider changing the architecture of my storyboard?
The fact that the view controllers in a navigation controller have child view controllers is not important. Only worry about the top-level view controllers that are pushed onto the navigation controller's stack. And only push/pop top-level view controllers, not children.
If you are having problems, you are probably doing something wrong, and will need to post a screenshot of your storyboard, along with the code that shows how you manage your navigation controller stack.
If you want your initial view controller to contain the proper subviews, you either need to hide/show what you need to make it to look like you want in viewDidDisappear as the user moves on to a new view, or you need to set it when they come back in viewWillAppear.
However your view is set up when you leave is how it will show up when you come back unless you change it. For example, in your root view controller:
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// hide your menu, clean up the view to prepare it for when user pops back
}
OR
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// if menu is showing, hide it. Clean up view before user sees it
}

How to add a subview to a UINavigation Controller without losing navigation bar?

I have a SplitViewController which has two UITableViewControllers - one master/root one detail. Everything works swimmingly.
I have a UIView which is shown on the detail view controller before the user selects an item in the root view controller. It's set up like this:
[self.navigationController.view addSubview:makeSentenceHelperView];
[self.navigationController.view bringSubviewToFront:makeSentenceHelperView];
The detailViewController is set up like so:
UINavigationController *detailNav = [[[UINavigationController alloc] initWithRootViewController:detailViewController] autorelease];
Where detailViewController is a subclass of UITableView.
The problem is that this subView hides the buttons and navigation bar from the detail view controller's navigation bar - which is a problem when you launch the SVC in portrait mode (there's no way to select a root item with the root popup).
How can I present the view inside the navigation controller, so that the navigation bar and buttons appear in the detail view?
Don't make detailViewController a subclass of UIView, instead go with UIViewController. So your splitView array will contain a instance of UINavigationController(rootVC) and other of UIViewController (detailVC).
Add a toolbar on the top of detailViewController and in landscape mode left side will be covered by your UITableView of rootVC and you will be able to see toolbar where you can add some button to its right side (will probably serve as navigation bar..:) . Rest of the things can be handled by UISplitViewControllerDelegate.
To fix this I added a UINavigationController to my helper UIView, and added a UIButtonBarItem to call the popover for selecting a new item in the master view. It seems really simple in retrospect. The only tricky bit will be making the UIButtonBarItem hide when in landscape.

Hidden UINavigationController inside UITabBarController

I have an application with 5 UIViewControllers each inside a corresponding UINavigationController, all tucked inside a UITabBarController that displays 5 tabs at the bottom of the screen.
I want to display another UIViewController (inside a UINavigationController) when a dialog button is pressed.
This view should only be loaded and unloaded programatically; i.e. it should not appear in the tab bar. However, I want the tab bar to be visible always.
If I add the [UINavigationController view] to [self window] the UITabBar is covered. If I add it to any other layer, the UINavigationController adds on the compensation it has for the status bar so appears further down than expected.
A solution would be to have the 6th UINavigationController added to the UITabBar with the others, but with its tabBarItem hidden. Then I can show it and hide it using the tabBars selectedIndex property.
Accessing the tabBarItem through the UIViewController shows no obvious way of doing this.
#wisequark, I think you completely misunderstood and you have almost rewritten the architecture of my application. However I have a separate navigation controller for each view as they are mutually exclusive and there is no concept of "drilling down".
#Kendall, This is what I expect I will have to do - have the modal view appear with a hide button to bring back the normal interface. But it would be nice to keep the tab bar always visible, so I was just wondering if anyone knew of a way.
It sounds as though you have a mess on your hands. A UINavigationController is a distinct object that is very different from a UITabBarController. In general, your application should have a tab controller, one of who's tab's loads a UINavigationController which in turn loads it's views - not that both maintain management over the different views. It is also improper to refer to the display of a UIViewController as such an object doesn't have a visual representation. In the case of a UINavigationController, the navigation controller object is responsible for displaying a navigation bar and a table view (in the most common case) and for managing the display of all the views in the navigation hierarchy. It itself has no corresponding representation on screen. Similarly, a UITabBarController presents a tab bar and is responsible for the loading and unloading of the views and/or view controllers attached to the tab buttons. If we were to present this as an image, it would look something like this -
alt text http://img.skitch.com/20081112-2sqp7q4wafa34te1ga337u4k8.png
Well, it sounds like what you really want to do is present a modal view with the tab bar still visible. You could add your view as a subview of the tab bar controller's view. The tab bar's view is, oddly enough, not the tab bar itself but rather a view containing the tab bar and the selected item's view.
Alternatively, you could try calling presentModalViewController:animated: with the selected tab (i.e. [tabBarController.selectedViewController presentModalViewController:animated:]) as the receiver instead of the tab bar. I seem to recall doing this once (quite by accident) and the tab bar remained visible.
One more thought: since each of your five view controllers is a UINavigationController, you could always pushViewController:animated: onto the selected view controller, then hide the back button. Your view will just appear without animation. But you'll need to remember to pop your view controller off the stack whenever the user switches to another tab. That might take a bit more work.
The best idea I could think of would be to either push a modal navigation controller for your view (which would hide the tab bar which you do not want), or to get the tab bar controller current selected view controller (really your navigation controller for a tab) and push your new view controller on there - and then pop that view when another tab is selected with a tab bar delegate.
It seems wierd to me to push the view onto random tabs though, if the view is created from a dialog that is modal, I don't see why the view itself should not also be modal and hide tabs.

Resources