Why does a segmented control hide when using a TabBarController? - ios

I want to use a segmented control inside a tab of a UITabBarController on iOS. It seems to work without it, but as soon as I embed it in a TabBarController, the segmented control won't show up in the navigation bar.
Am I missing something or is it just not supported because of some UI-guidelines? I haven't found anything in the Apple Design Guidelines...
This is the working version:
But in this setup, the segmented control does not show up:

First question is: What are you trying to achieve - what interface do you want to provide?
It is very uncommon to have a tab bar controller embedded in a navigation controller.
A tab bar controller is meant to be used as main app navigation. You can find it in so many Apple Apps (Music, Phone etc.)
These Apps have a tab bar controller with multiple navigation controllers. For example your first tab is a navigation controller with a normal view controller as root.
In this controller you then can set you segmented control.
Apple describes this behavior in it's Combined View Controller Interfaces Documentation (https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/CombiningViewControllers.html#//apple_ref/doc/uid/TP40011313-CH6-SW1).
Update
#kaushal answer solves your problem ... yes. But if you will try to style the navigation bar for every view controller contained in your tab view controller (maybe you want to add a button as rightBarButtonItem only for one view controller) this won't work.
If you want a segmented control on every controller of the tab view controller just isolate the code for this control and reuse it in every controller.
This would achieve the same effect but you would have a cleaner software design.

try this :
Navigation bar is common throwout the stack, It will load once. And it was empty for first view. If you want it customisable for particular VC then you have to do it programatically by accessing self.NavigationBar in view did load method.

Related

How to Share a View Across a Navigation Hierarchy with No Animation?

I have a simple Navigation View Hierarchy that has 2 views it goes between. I wanted a customized navigation bar, so I have the default one hidden, and I've implemented a Container View which is shared between the 2 views in the nav hierarchy.
Everything works as I want it to, except when I segue to the lower or higher view the top bar appears slides away and reappears on the new view. I would like it to appear stationary when I push or pop to other views in the hierarchy.
Is there an easy way to do this? Or should I delete my custom shared Container View and try to make this work with the Navigation Bar (which I have currently "hidden")?
I had to do this for a client once. The way we did it was, like you said, make an encompassing view controller that housed a container view. Within this container view, we embedded a UINavigationController and would manually pop and push UIViewControllers to its navigation stack. Of course you want to hide the UINavigationController's nav bar.
It sounds like you sort of implemented this, but instead you just embedded a plain old view controller inside your custom navigation controller, and then segue to another view controller that is also embedded in the custom view controller? Ideally you want one instance of this custom nav controller with an embedded UINavigationController. I believe you will have to do all the view controller transitions programmatically.
Opinion: Personally, I would recommend against doing this. I believe that an app should feel like an extension of the OS it's on. A user should feel it's a part of their phone. Using the native navigation bar also decreases the level of effort a user is required to put forth to understand your app.
I know you're thinking "but it's just a nav bar" but we're talking about the same people that will potentially uninstall an app if it takes longer than 2.5s to load.
I wanted a customized navigation bar, so I have the default one hidden
That's your mistake. The way to get a customized navigation bar in a UINavigationController interface is to initialize it with init(navigationBarClass:toolbarClass:). Now the built-in navigation controller is using your navigation bar! And from there on, all will be well.
https://developer.apple.com/reference/uikit/uinavigationcontroller/1621866-init

Xcode 6 - Swift - Custom Tabbar with Navigation

I'm trying to create a tabbed application with navigation elements inside the tab bar, as seen in the picture below (the red bar) using Swift/XCode 6.2. Basically those three icons in the middle will direct the user to different view controllers. The other two icons would be context-based. For example, on a table view page you would see the menu icon and add new icon as seen in the image. However, clicking on a row would change the menu icon to a back icon, and the add icon to something else.
That's the general idea, but I'm having a very hard time implementing something even close to this. The first issue is that whenever I embed a view in a Tab Bar Controller, I can't move the tab bar to the top. However, when I create a custom UITabView in a View Controller, Control + Click and dragging a Tab Bar Item to another view doesn't create a segue. I haven't even begun to tackle having the navigation elements inside the bar.
I guess what I'm asking is just for a little guidance on what route to take to tackle this. I'm assuming I can't use a Tab Bar Controller or Navigation Controller because it doesn't seem like I can customize them all that much. So custom Tab Bar and Navigation Bars, and then implemnt the segues and button changes programmatically?
Thanks.
I will try to guide you from an architectural perspective (so you won't find much code below).
Using a UITabBarController
In order to achieve what you are suggesting, you are right you cannot use a UITabBarController straight away, among several reasons, the most immediate one is that they are meant to be always at the bottom and you want it in top (check Apple's docs). The good news is that probably you don't need it!
Note: If you still want to go with a UITabBarController for whatever reason, please see #Matt's answer.
Using a UINavigationController
You can use a UINavigationController to solve this task, since the UINavigationBar of a UINavigationController can be customized. There are multiple ways on how you can organize your view's hierarchy to achieve what you propose, but let me elaborate one option:
To customize a UINavigationBar's to add buttons, you just need to set its navigationItem's title view:
// Assuming viewWithTopButtons is a view containing the 3 top buttons
self.navigationItem.titleView = viewWithTopButtons
To add the burger menu functionality on a UINavigationController you can find several posts on how to do it and infinite frameworks you can use. Check this other SO Question for a more detailed answer (e.g. MMDrawerController, ECSlidingViewController to mention a couple).
About organizing your view hierarchy, it really depends on if when the user taps one of the main top buttons, it will always go to the first view controller in the new section or if you want to bring him back to the last view in the section where he was.
3.1 Switching sections displays the first view of the new section
Your app's UIWindow will have a single UINavigationController on top of the hierarchy. Then each of the 3 top buttons, when tapped, will change the root view controller of the UINavigationController.
Then, when the user changes section, the current navigation hierarchy is discarded by setting the new section view controller as the UINavigationController root view controller.
self.navigationController = [sectionFirstViewController]
3.2 Switching sections displays the last displayed view in the new section
This will require a slightly modified version of the above, where your each of your sections will have its own UINavigationController, so you can always keep a navigation hierarchy per section.
Then, when the user taps one of the top buttons to switch section, instead of changing as previously described, you will change the UIWindowroot view controller to the new section's UINavigationController.
window.rootViewController = sectionNavigationController
Using a custom implementation
Of course, the last and also very valid option would be that you implement yourself your own component to achieve your requirements. This is probably the option requiring the biggest effort in exchange of the highest customizability.
Choosing this option is definitely not recommend to less experienced developers.
I'd like to take a stab at this--I think it is possible to use a tab bar controller here.
Your topmost-level view controller will be a UITabBarController with a hidden UITabBar.
Each tab is contained in a UINavigationController.
All view controllers in the navigation controller will be a subclass of a view controller (say, SwitchableViewController).
In SwitchableViewController's viewDidLoad, you set the navigation item's title view (i.e. whatever's at the center; self.navigationItem.titleView) to be the view that holds the three center buttons. Could be a UISegmentedControl, or a custom view.
Whenever you tap on any of the buttons, you change the topmost UITabBarController's selected index to the view controller you want to show.
Issues you may encounter:
Table views inside tabs will have a scrollIndicatorOffset at the bottom even if the tab bar is hidden.
Solution: Play around with the automaticallyAdjustsScrollViewInsets of the tab bar controller, or the inner view controller. https://stackoverflow.com/a/29264073/855680
Your title view will be animated every time you push a new view controller in the navigation stack.
Solution: Take a look at creating a custom transition animation for the UINavigationController.

Difference between navigation controller and viewcontroller?

Difference between navigation controller and viewcontroller?
I mean how can we decide when to use navigation controller or a normal view controller?
Just my two cents:
A UIViewController represents a single view and you can put buttons in this view controller to segue to another UIViewController. If you want to segue back to the first UIViewController, you will have to worry about putting a button in the second view controller that leads back to the first. If you are drilling down into view controllers, this can be tedious having to remember to give the user a way back to a previous view controller.
A UINavigationController does a lot of this tedious work for you. As mentioned, it contains a stack of UIViewControllers. It will create a navigation bar at the top that will allow you to easily go back up the hierarchy of view controllers.
In short, if you have a hierarchy of view controllers that you want the user to easily navigate around, inbed your UIViewControllers into a UINavigation controller.
UINavigation Controller is a combination of 2 or more view controllers,those are connected through "segue" feature of "Ios". Benefit of using Navigation Controller is that we can navigate between different screens easily with default "Back" button on each screen . We don't need to give any individual button to move back onto previous screen.
Whereas a ViewController provides a single screen & we can connect more screen using "segue" but we also have to design a "Back" button to navigate onto previous screen.
We should use Navigation Controller , in case where one option resides into another one.Like in an iPhone settings ->Mobile Data Options->Voice->4G or 3G or 2G. It's a hierarchy of menus so here navigation Controller is better option than using UIController.
We should use UiController with "segue " , in case where
we have to choose one option among multiple.Like -
Photos ->There are many folders in which , any one is selected, that are Favourites or People or Places .
Here's a very brief, high-level overview.
Whereas a UIViewController can be thought of as representing a single 'screen', UINavigationController, as the name implies, is used as a means of being able to navigate multiple 'screens'.
From the documentation:
The UINavigationController class implements a specialized view controller that manages the navigation of hierarchical content. This navigation interface makes it possible to present your data efficiently and makes it easier for the user to navigate that content. You generally use this class as-is but in iOS 6 and later you may subclass to customize the class behavior.
Please see the rest of the UINavigationController documentation here: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/index.html
Okay, Thank you everyone for helping me to find out a clear answer on this.
Navigation Controller consists of navigation bar and tool bar to move in and out from view controllers present in navigation stack.Therefore there can be many view controllers in Navigation Controller.
In view controller we don't have this facility and it represents a single screen view.
Please correct me If I am wrong.
See the Navigation Controller discussion in the View Controller Catalog.
Bottom line, a navigation controller actually is a view controller, but it just happens to be one that presents and navigates between other view controllers.

IPad Split View Implement in Another View

I am creating a iPad App and it has several views to load data,but for one view i need to add split view. I dont need split views in other views. They are just detail pages. I search Through the net and found lots of tutorials based on iPad split view. But the problem is they all are creating a project as Split view project or they create a window base app and add slipt view to the delegate. I dont need to do that, I need to implement this split view only for one view. Is There any way to overcome this problem?
You can add the split view inside a Navigation Controller.
Even if the Split View is a container view controller and Apple recommends in the documentation that all containers should not be embedded in other containers, adding a split view inside a navigation controller works correctly and I never noticed any side effect in doing it.
Basically what you should do is:
- in the app delegate create a UINavigationController and use it as root view of your application window
- hide the navigation controller navigation bar if you don't want to see it (showing a split view with a main navbar on top is not nice looking...)
- then add your view controllers inside the navigation bar.
Example: imagine you have this application views sequence:
FIRST VIEW (full view = detail page)
SECOND VIEW (split view)
THIRD VIEW (full = detail page)
So you can represent FIRST and THIRD as standard view controllers (full screen), while SECOND will be a split view. Your app will be initialized by creating the main navigation controller, adding FIRST on it as top controller and using the main navigation controller as window's root view.
Than use the navigation controller push, pop methods to switch between these views or change the navigation controller "viewControllers" array directly if you don't want the recommended push/pop methods.
If you need to add special behavior to the navigation controller based on the type of view on top, just register your app delegate as navigation controller delegate (or a "main controller" object dedicated to this if you don't want to complicate your app delegate).
I am not 100% sure, but it seems to me that you can't use a SplitView just somewhere in your view hierarchy.
The Apple intended way is to use the SplitViewController as the top level controller. The left side of it can include a drill down mechanism with a navigation controller so you are ably to drill down hierarchies and the right side will present details for the item you select on the left side.
If you need a view with some kind of split mechanism in it, you probably have to code it yourself. Or even better: find some other mechanism you can use in your UI.
How are you switching your view hierarchies now? Maybe you could integrate your existing UI into a SplitViewController?

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