I have four tabs in the TabBarController which is my home controller. Then I have a tableView in the first VC. When I use didSelect method to call splitViewController using present, it will come on top of tab bars at the bottom.
How would I bring the splitViewController above my First VC but behind the tabBar at the bottom? I tried to put the splitViewController inside normal ViewController, it looks ugly and I do not want to do that.
Thanks in Advance.
I'm not sure I understood the question correctly, but if you want to put a UIViewController on top of another UIViewController, while visibly staying in the same tab of a UITabBarController, the standard approach would be to use a UINavigationController:
Instead of adding the ViewController containing your tableView directly to the TabBarController, try wrapping in in a UINavigationController first, e.g. by creating one with UINavigationController(rootViewController: <UIViewController>).
Then, on didSelect inside your TableView-ViewController, instead of using present on the TableView-ViewController itself, use pushViewController(<UIViewController>, animated: <Bool>) on the TableView-ViewController's optional .navigationController property.
If you don't like the appearance of the UINavigationController's navigation bar, you can customize or even hide it completely (but that's a different topic).
Related
The Problem
I'm relatively new to Swift and I'm trying to build an application that makes use of a UITabBarController.
What I'm trying to do is put a different navigation bar (or UINavigationItem) on each of the tabs in the UITabBarController.
For example, I want the UINavigationItem I set, with its bar button items, to appear on MyViewController instead of a back button to the previous view controller, such as shown on the image below.
The current layout on the Storyboard is as follows.
MyViewController on the sidebar:
What I've Tried
Someone suggested that I should embed each UIViewController (e.g. MyViewController) in a Navigation Controller. I've tried this and it doesn't work.
I've also tried to set the Top Bar to "None" in the Attributes tab of the options menu.
Thank you in advance for your help.
Here is how i did it,
UINavigationController -> UITabbarController
And then each "Tab" is in different Storyboard and every storyboard start with a "Navigation Controller". So yes every tab in different navigation controller this how you should do it.
Different storyboards because may be multiple people work on storyboard at same time.
Why TabbarController inside Navigationcontroller ?
I put the "TabbarController" inside "NavigationController" because some of the controllers i want them to be full screen, like hiding the "Tabbar" so for that i push them from main NavigationController.
//Out of context but may help you,
I have created an "Extension" of Navigation Controller to push a view controller on main navigation so that any of the tabbars (which are also inside navigation controllers) can easily use the extension to push any view controller if want to hide the tabbar.
In the interface builder I have a UITabBarController and it is set as the initial view controller. From the tab bar controller, I have linked three independent ViewControllers; two UIViewController's and one UITableViewController. I have embedded all three of these views inside UINavigationController's as each of these views will eventually segue to a new view.
Interface Builder
Problem:
I now want to link one of the UIViewController's to the UITableViewController using a button to segue to the table view. This way I can pass information, i.e. func prepareForSegue(), to the table view. I want to maintain the tab bar controller at the bottom, however I do not want to have the ability to go back to the previous UIViewController from the current UITableViewController via a UIBarButtonItem at the the top of the view; That is what the tab bar at the bottom is for.
However every time I segue "Show" the table view (it is actually a segue to the table views navigation controller), the navigation bars at the top and the bottom of the table view disappear. Is there anyway to prevent this from happening?
I have also tried segue "Show" directly to the table view, in which case the tab bar is visible, but then it displays a "back" button at the top of the view to segue back to the sending UIViewController. I am hesitant about accepting a solution that would just hide the back button, because I feel I will run into problems down the road when I want to navigate to a detail view from the table view itself, since I would be bypassing the UITableViewController's UINavigationController.
Any solutions would be greatly appreciated. I have been trying to solve this problem for hours and I'm about to put my head through my computer screen. Also I thought about just using tabBarController?.selectedIndex on the button click to shift to the table view, and then passing the information using NSUserDefaults, but this is out of the question since I would be passing a custom object, and would have to encode and decode every custom field.
I you use a segue to get to it, as you say, you will still be using the UIViewController's UINavigationController which seems a bit messy. So I actually think selectedIndex is probably the best way to go as once you change to the UITableViewController you'll be in the correct navigation stack.
Instead of using NSUserDefaults, why not just reference the UITableView itself from the UIViewController, set the values you want, and then swap to it using self.tabBarController.selectedIndex.
So for your scenario above it, assuming the UITableViewContollrer is the third view in the UITabBarController, you would do something like the following:
Pass whatever you want into the UITabBarController by setting some pre-defined var in it. For example, if there was a String called saveMe in the UITableViewController, then do the following in the UIViewController:
let navController = self.tabBarController?.viewControllers![2] as! UINavigationController
let tableViewController = navController.viewControllers.first as! JarListTableViewController
tableViewController.saveMe = "Saved string here"
Swap to the UITableViewController using:
self.tabBarController?.selectedIndex = 2
The only issue with this is using selectedIndex won't perform a transition animation but not sure if you need this. This link could help if you do.
I've tried a lot to get this done.I don't want want to use addsubview or uitabbarcontroller. I want to switch the view when I tap on different tabs and tabbar should stay there. Thanks a lot in advance.I m a newbie.I want to use uitabbar not uitabbarcontroller.
A simple approach would be to wrap the view controllers you are inserting in UITabBarController in a UINavigationController then you can simply push your new view to that UINavigationController and the tab bar would be always visible!
For more details refer Apple Docs
Edit:
If you don't want to use UITabBarController then you need to do 2 things:
Add the tab bar View to UIWindow that way it would be always visible.
Scale/adjust the views in your view controllers to leave space for the tab bar
So... I've got a ViewController that's being pushed onto a NavigationController. In interface builder I create a separate ViewController and Embed it into a TabBarController and it looks good in Interface Builder.
In my app, I'm trying to go from one of the ViewControllers in my NavigationView to the ViewController in the TabBarController. How would I do this the correct way? I can't just push the view onto the NavigationController, because the tab bar at the bottom won't show up.
Any help would be greatly appreciate.
I believe you're operating with the UINavigationController and UITabBarController in a backwards order to recommended best-practice.
Unless something has changed in the last year or two (which may have happened) the UINavigationController should never have a UITabBarController pushed onto it. If you are using a UITabBarController in your app, it should be the window.rootViewController, and the navigation controller being member of the UITabBarController's viewControllers array.
I'm trying to go from one of the ViewControllers in my NavigationView
to the ViewController in the TabBarController. How would I do this the
correct way?
In that structure, you'd assign your destination view controller as another element of the viewControllers array. Then, in my style, I'd send a NSNotification something like "LaunchOtherViewController" from your first view controller, and thus you have no need for the first view controller to know about the tab bar controller or second view controller. Then have some class that knows about the second view controller receive that notification, and update the selectedIndex of the UITabBarController to that of the second, destination view controller.
Hope that makes sense.
You need to push the TabBarController onto the view. You may need to set the selected view controller of the tab bar, but it's important the tab bar controller be actually pushed onto the navigation stack (or presented modally).
I've seen a lot of other questions on here about adding a UINavigationBar to a UIPopoverController. All of the examples I've seen follow one of two patterns:
In the init or viewDidLoad method of the Popover subclass, you alloc-init a UINavigationBar directly, as suggested here. This method is a little hacky, and while it shows up nicely, if the popover is a UITableViewController, you have to mess with a bunch of things to make sure the navigation bar you just added doesn't overlap one of your cells.
Alternatively, a lot of post suggest creating a UINavigationController just before presenting the popover, as shown here.
With the second method, however, won't the popover be the only controller in the newly created navigation controller? And if my view that I'm presenting the popover from is itself already in a navigation controller, the popover will NOT be in that same navigation controller, correct? It seems to be that the more appropriate thing to do would be to add the popover being created as another controller in the navigation controller that already exists (and which the controller that presents the popover is already a part of). Is that possible? Or is there a reason why the navigation controller for the popover needs to be independent from the navigation controller for the presenting controller? Or am I totally missing something here?
You have many questions, young Skywalker. :)
Creating a UINavigationController and then embedding the controller you would like to present is the way to go.
Don't get confused by all the controllers involved here:
UIPopoverController is a construct that shows an existing UIViewController in an overlay like style. UIPopoverController itself even isn't a subclass of UIViewController. The name is misleading.
So UIPopoverController hosts another controller. In your case, we let it host a UINavigationController.
UINavigationController is a subclass of UIViewController. It is a container controller and can handle a stack of UIViewControllers.
On that stack we push one UIViewController: the one you want to display and garnish with a UINavigationBar. Since Mr. UINavigationController comes with a build in UINavigationBar, he's our friend.
There is no need to subclass UIPopoverController. You just keep one static reference to it around so you can dismiss the current open popover in case you want to present another.
It does not matter where you present the UIPopoverController from. It will always be a popover. Even if presented from an existing UINavigationController. Only if you use presentViewController: you will get different results depending on the controller you're presenting from (modal or pushed on top of the stack).
won't the popover be the only controller in the newly created navigation controller?
No, the popover will contain the navigation controller and the navigation controller will only contain its root view controller (which would otherwise have been added directly to the popover as its root).
You seem to be a little confused about the relationship between the popover and the popover root view controller...
the popover will NOT be in that same navigation controller, correct
Yes, correct. The popover is effectively a window floating above all other views
Or am I totally missing something here?
Maybe... The popover would usually be used for displaying something modal, transient and smaller than full screen size. Putting a navigation controller in the popover and adding views to it is the normal approach.
Adding a navigation bar to a popover isn't hacky. A navigation bar is just another regular view. That also means that using a UITableViewController with it, the navigation bar will overlap the table view, as the UITableViewController's view property just returns the controller's tableView property. If you want to add a navigation bar above a table view, without it overlapping the table view, use a regular UIViewController and add your navigation bar and table view the normal way. UITableViewController should only be used if your only view within that view controller is a table view.
Having said that, I do agree with others that just using a navigation controller without using its navigation features is the most common approach.