I have an existing UITableViewController that I've embedded in a NavigationController. However, the Navigation Bar is not showing when I present the view.
Presenting the TableViewController (its Storyboard id is: SelectServicesController) :
if let selectServicesController = self.storyboard?.instantiateViewControllerWithIdentifier("SelectServicesController") as? UITableViewController {
self.navigationController?.presentViewController(selectServicesController, animated: true, completion: nil)
}
This is what it looks like when I build (nav bar does not show):
So I just did this and at fist could not get it to show up at all. Then Figured it out, You just need to select the navigation controller and set it to be the ✅is initial View Controller
This is what your storyboard should look like
Then to make everything show up I added this to my viewDidLoad of the view the Navigation controller is presenting. This step is more optional.
self.navigationController?.navigationBar.barTintColor = UIColor.redColor()
self.navigationController?.navigationBar.tintColor = UIColor.blackColor()
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.blackColor()]
navigationController?.navigationBar.hidden = false
And this is what it looks like
mmmm Red on black 🤓 Hope that helps you.
You're presenting a UITableViewController, which doesn't have a navigation controller as a parent (even though your Storyboard has it first, you're not actually using it).
You can fix this by doing something like this:
if let selectServicesController = self.storyboard?.instantiateViewControllerWithIdentifier("SelectServicesController") as? UITableViewController {
let navigationController = UINavigationController(rootViewController: selectServicesController)
self.navigationController?.presentViewController(navigationController, animated: true, completion: nil)
}
Or by setting the navigation controller as the initial view controller of the storyboard and then calling it like this:
if let selectServicesController = self.storyboard?.instantiateInitialViewController() {
self.navigationController?.presentViewController(selectServicesController, animated: true, completion: nil)
}
I encountered the same problem. I solved it by Changing the segue to the navigation controller that embeds the View Controller I want to display.
Hopefully it would work for you.
Let me know if it is a bad practice.
let storyboard = UIStoryboard(name: "Expense", bundle: Bundle(for: PTCAddExpenseViewController.self))
let controller = storyboard.instantiateViewController(withIdentifier:"AddExpense") as! PTCAddExpenseViewController
let navigationController = UINavigationController(rootViewController: controller)
self.present(navigationController, animated: true, completion: nil)
Adding this works for me:
self.navigationController?.isNavigationBarHidden = false
You're presenting the table view controller directly, not its navigation controller. If you mark the nav controller as the initial view controller (tick the "Is initial view controller" box in the attributes inspector), then you can instantiate and show it by:
if let selectServicesNavController = self.storyboard?.instantiateInitialViewController() as? UINavigationController {
// if you're pushing it onto an existing nav controller
self.navigationController?.presentViewController(selectServicesNavController, animated: true, completion: nil)
// if not (and this is probably the case), set the nav controller as your window's rootViewController
UIApplication.sharedApplication().keyWindow.rootViewController = selectServicesNavController
}
My guess is Xcode is ignoring the fact that your table view controller is embedded in navigation controller when presenting your table view controller with the following code:
if let selectServicesController = self.storyboard?.instantiateViewControllerWithIdentifier("SelectServicesController") as? UITableViewController {
self.navigationController?.presentViewController(selectServicesController, animated: true, completion: nil)
}
Instead, I would suggest you modify the Top Bar setting under Simulated Metrics to suit your needs or instantiate your navigation controller instead (the latter is preferred and recommended)
In your code, change this line
self.navigationController?.presentViewController(selectServicesController, animated: true, completion: nil)
to this
self.presentViewController(selectServicesController, animated: true, completion: nil)
I read in one of your comments you want to present the table view controller modally, with the navigation bar showing. We can do this using the Storyboard. From the view controller that should display this table view controller modally, Ctrl+Drag from the view controller to the Navigation Controller of the Table View Controller. Then, select Present Modally. Set an Identifier for the segue. Then, in your code for the view controller that is presenting the table view controller modally, call:
self.performSegueWithIdentifier("YourSegueIdentifier", sender: nil)
Another way to do this without having to use any code is if the modal presentation is being triggered by something like a button. Then, you can Ctrl+Drag from that button to the Navigation Controller and select Present Modally.
Or it might be this!!
I had the same problem: the navigation bar was showing on the root view in Storyboard, but when running the Simulator - there was no navigation bar at the top of the views. This solved it:
Navigation Controller > Navigation Bar > UNCHECK Translucent (it is checked by default). This did two things:
My Navigation Bar shows on all subsequent views.
The topmost subview is now at Y=0, and not Y=64.
Related
I have a view controller embedded in a navigation controller. I settled the navigation controller modal presentation full screen:
let firstVC = FirstViewController()
customNavigationController = CustomNavigationController(rootViewController: firstVC)
customNavigationController.modalPresentationStyle = .fullScreen
self.navigationController.present(customNavigationController, animated: true, completion: nil)
In the "firstVC" I need to present another view controller with modal presentation style .pageSheet:
class FirstViewController {
func presentSecondVC() {
let secondVC = UIViewController()
secondVC.modalPresentationStyle = .pageSheet
present(secondVC, animated: true, completion: nil)
}
}
The result is this.
This is not what I want. I want the default presentation, like this.
My problem is that I need the full screen presentation for all the controllers that will be presented in the flow, but only in one case I need the pageSheet presentation with the default iOS graphic.
Is that possible?
I think that default tools cannot help you. And way to try to manage presenting view is not good idea.
So one way to get what you want is to make custom view like standard .pageSheet view, and then you present it with .fullScreen modal presentation.
Can someone help me with this? :(
The navigation bar is not appearing. This is presented by a rootViewController.
You have not posted any code still guessing.
Just taking UINavigationController in storyboad doesn't means that it will appear by default.
You are just presenting view controller. You need to embed in navigation controller or give storyboard identifier to navigation controller and present that.
Example :
let yourviewController = self.storyboard?.instantiateViewController(withIdentifier: "yourVCIdentifer")
let nav = UINavigationController(rootViewController: yourviewController)
self.present(nav, animated: true, completion: nil)
I have created a simple tab bar with three views in storyboard. The tab bar works well, but when I try to show another view controller from a button within a tab, the new view is placed over the whole screen and also over the tab bar.
This is how I present the view so far when a button is pressed:
#IBAction func buttonPressed(_ sender: UIButton) {
let newVC = self.storyboard?.instantiateViewController(withIdentifier: "extraVC")
self.present(newVC!, animated: true, completion: nil)
}
The other idea I had was this:
self.tabBarController?.present(vc!, animated: true, completion: nil)
But this didn't work either.
So how can I present another view controller within the tab bar (so that the bottom bar is still shown)?
When you present a view controller modally, its presentation style will be "Full Screen" by default. What you want to do is have it do in this case is just cover part of the screen (the part where the presenting view controller is drawn.
One way to accomplish this is to:
Set the modalPresentationStyle for the presented view controller to be .currentContext or .overCurrentContext
In the view controller that will be presenting the modal, set its definesContext property to true.
These steps can be done either in Interface Builder by setting attributes on the segue and the view controller, or you can modify your code to include the following:
#IBAction func buttonPressed(_ sender: UIButton) {
let newVC = self.storyboard?.instantiateViewController(withIdentifier: "extraVC")
self.definesPresentationContext = true
newVC?.modalPresentationStyle = .overCurrentContext
self.present(newVC!, animated: true, completion: nil)
}
What this combination of properties does is:
Indicate for the presented view controller that you want it to be presented in a non-full screen context (some specific section of the screen)
Indicate that the presenting view controller is in the section of the screen / the context you want the modal to be drawn according to.
More details can be found in the Apple Documentation
When you are using present method, the ViewController is presented modally and covers your UITabBarConntroller. Instead of showing your view modally you can embed every first view controller in your TabBar into UINavigationController and then use method pushViewController to push it onto stack. You will have your TabBar visible and nice looking animation for free.
In Xcode, I created a new project using the Tabbed App template to illustrate the solution above. This will create a project with a tabbar controller and two view controllers. I added a button with the title "view page" to the first view controller and embedded a navigation controller from the storyboard.
The storyboard will look like this after making the above changes:
In the FirstViewController.swift file, I created an IBAction for the button with the following code that will create another view controller called DetailViewController, with the title Favorites and a background color of orange. I used the navigation controller to present it by pushing it onto the navigation controller stack.
#IBAction func viewPageButtonTapped(_ sender: UIButton) {
print("viewPageButtonTapped")
let pinkViewController = DetailViewController()
pinkViewController.title = "Favorites"
pinkViewController.view.backgroundColor = UIColor.orange
navigationController?.pushViewController(pinkViewController, animated: true)
}
When I run the project on the simulator, I got the desired result. Hope this helps give you some ideas.
In your viewController do:
self.tabBarController?.present(nextViewController, animated: true/false, completion: {})
On clicking a button I display a view controller using the following code:
let navController = UINavigationController(rootViewController: locationVC)
navController.navigationBar.barTintColor = StyleHelper.navBarColor()
navController.navigationBar.tintColor = UIColor.whiteColor()
navController.navigationItem.backBarButtonItem = UIBarButtonItem(image: UIImage(named: "back_arrow"), style: .Plain, target: locationVC, action: nil)
self.presentViewController(navController, animated: true, completion: nil)
But the back button does not appear on the locationVC
What am I doing wrong? Please help
Multiple issues with code.
Issue 1:
You should update viewController's bar button item and not navigationController's bar button item.
So this is wrong
navController.navigationItem.backBarButtonItem
Whats correct
self.navigationItem.backBarButtonItem
Issue 2:
The above code won't work because your current viewController is not pushed by any other VC so it cant show back button. What you need is leftBarButtonItem
So in your VC you can write
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Abcd", style: .done, target: self, action: yourSelectorHere)
}
O/P:
Back button only appears for view controllers in the navigation stack.
you creating new navigation controller stack and making locationVC as root controller so there won't be any view controller to go back.
If you push another view controller to the navigation stack then you will get back button.
In a horizontally regular environment, the view controller is
presented in the style specified by the modalPresentationStyle
property. In a horizontally compact environment, the view controller
is presented full screen by default. doc: presentViewController
So, if you use present a view controller it will not show in navigation controller thus no back button
For this case you need to push view controller.
From storyboard:
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier:
"newViewController") as! YourViewController
self.navigationController?.pushViewController(vc, animated: true)
Programmatically
let vc = YourViewController()
self.navigationController?.pushViewController(vc, animated: true)
presenting will present your VC on top of everything and not push it to the navigayionCOntroller.
You should push your VC to the NavigationController instead like so:
var rootViewController = self.window!.rootViewController as UINavigationController
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var profileViewController = mainStoryboard.instantiateViewControllerWithIdentifier("profile") as ProfileViewController
rootViewController.pushToViewController(profileViewController, animated: true)
presentViewController is a method that bring a modal view to your navigation, not part of the navigationController.
Instead you should use the pushToViewController method on the navigationController (and not creating a new one) like that :
if let navigationController = self.navigationController {
navigationController.pushViewController(locationVC, animated: true)
}
The presenting view controller is responsible for dismissing the view controller is presented. If you call this method on the presented view controller itself, UIKit asks the presenting view controller to handle the dismissal.
If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.
If you want to retain a reference to the view controller's presented view controller, get the value in the presentedViewController property before calling this method.
#IBAction func backButtonAction(_ sender: UIButton) {
self.dismiss(animated: true)
}
More: https://developer.apple.com/documentation/uikit/uiviewcontroller/1621505-dismiss
I am trying to display a fix navigation bar for my UiTableViewController, I have a first ViewController and when I click on it, this will open my UITableViewController Here is the code of the click :
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("MyTableViewController") as! MyTableViewController
vc.myObject = object // I pass some data
presentViewController(vc, animated: true, completion: nil)
the UItableView is correctly display but not navigation bar appear, if I add one, the navigation bar scroll with the table view and I don't want this behavior.
I tried this without success :
Go to the Editor menu, and click on the Embed In submenu, and choose
Navigation Controller
And tried to change some settings here :
Actually, in your case you want to show navigation and for navigation you have to push your view controller to a UINavigationController thats why the solution is :
let vc = storyboard.instantiateViewControllerWithIdentifier("MyTableViewController") as! MyTableViewController
vc.myObject = object // I pass some data
self.navigationController?.pushViewController(vc, animated: true)
presentViewController offers a mechanism to display a modal view controller; i.e., a view controller that will take full control of your UI by being superimposed on top of a parent controller & establish a parent child relation b/w presenting & presented view controllers.
where as
pushViewController offers a much more flexible navigation process where you can push & pop a new controller to UINavigationController, so to go back to the previous one, in a ordered way. Imagine that controllers in a navigation controller will just build a sequence from left to right like building a stack of view controllers stacking upon each other.
Do it this way:
let vc = storyboard.instantiateViewControllerWithIdentifier("MyTableViewController") as! MyTableViewController
vc.myObject = object // I pass some data
self.navigationController?.pushViewController(vc, animated: true)