Why is hidesBottomBarWhenPushed not working when not root view controller? - swift

A view controller is pushed and the bottom tab bar is hidden like so:
let myViewController = self.storyboard?.instantiateViewController(withIdentifier: MyViewController) as! MyViewController
myViewController.hidesBottomBarWhenPushed = true
navigationController?.pushViewController(myViewController, animated: true)
That works fine.
However when I change the root view controller before the push the bottom bar is not hidden.
// Change the root view controller
let firstRootViewController = UIApplication.shared.keyWindow!.rootViewController
UIApplication.shared.keyWindow!.rootViewController = secondRootViewController
// Push view on stack of navigation controller which is a child of firstRootViewController
let myViewController = self.storyboard?.instantiateViewController(withIdentifier: MyViewController) as! MyViewController
myViewController.hidesBottomBarWhenPushed = true
navigationController?.pushViewController(myViewController, animated: true)
// Some more things happen...
// Switch back to previous root view controller
UIApplication.shared.keyWindow!.rootViewController = firstRootViewController
The result is that the navigation controller pushed the myViewController correctly but the bottom bar is visible, as if the parameter hidesBottomBarWhenPushed was ignored.
What's wrong here?

The solution was to not change the root view controller but to only add the view to the keyWindow:
// Add another view on top of all views
UIApplication.shared.keyWindow?.addSubView(self.view)
// Push view on stack of navigation controller which is a child of firstRootViewController
let myViewController = self.storyboard?.instantiateViewController(withIdentifier: MyViewController) as! MyViewController
myViewController.hidesBottomBarWhenPushed = true
navigationController?.pushViewController(myViewController, animated: true)
// Some more things happen...
// Remove topmost view
self.view.removeFromSuperview()

Related

Swift How can I add Navigation Controller after creating Views

I created View Controllers and I want to add Navigation Controller now. I tried embed-in Navigation Controller to My DetailViewContoller(colorful View Controller) but I got an error. main.storyboard, error. How can I add Navigation Controller ?
In order to set view controller as navigation controller, you can set it programmatically by calling this function in appdelegate or scenedelegate or any point.
func setNavigationController() {
var viewController: UIViewController
let storyboard = UIStoryboard(name: "myStoryboardName", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "myVCID")
let rootViewController = UINavigationController(rootViewController: viewController)
rootViewController.setNavigationBarHidden(true, animated: false)
self.view.window?.rootViewController = rootViewController
}
If you want to set navigation controller through storyboard, then you have to first add navigation controller and set is root view controller to the controller you want to make it navigation controller.

How to do popViewController from another class?

My app has a TabBarController. Each tabBarItem relates to a ViewController embedded in a NavigationController.
When in first tabBarItem and selecting another tabBarItem I want to do some stuff before moving to the selected ViewController. Therefore I created a class for my tabBarController and made it UITabBarControllerDelegate.
What I want to do is present an alert with two buttons; button A cancels the move to the selected viewController and button B lets the move happen.
My problem is that when button B is pressed, I want to popToRootViewController. I gave the navigationController a storyboardID and tried to instantiate it like shown below.
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if let alert = self.storyboard?.instantiateViewController(withIdentifier: "ActiveSessionWarningAlert") as? ActiveSessionWarningAlert {
alert.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
alert.modalTransitionStyle = UIModalTransitionStyle.flipHorizontal
let alertWasDismissed: (Bool) -> Void = { userWantsToMoveToSelectedViewController in
if userWantsToMoveToSelectedViewController {
if let navContr = self.storyboard?.instantiateViewController(withIdentifier: "firstNavContr") as? UINavigationController {
navContr.popToRootViewController(animated: true)
}
tabBarController.selectedViewController = viewController
}
}
alert.alertWasDismissed = alertWasDismissed
self.present(alert, animated: true, completion: nil)
}
return false
}
Everything works as expected, but the popToRootViewController doesn't seem to occur; when selecting the first tabBarItem again the same viewController that was 'active' when we left the item is still showing.
I checked so that the viewController I want to pop is actually in the navigation stack and that the navContr != nil.
What am I missing?
You don't say so, but I'm assuming that the alertWasDismissed closure you pass to your alert view controller gets invoked when the user dismisses the alert.
The problem with your closure is this bit:
if let navContr = self.storyboard?.instantiateViewController(withIdentifier: "firstNavContr") as? UINavigationController
Any time you call instantiateViewController(withIdentifier:), you are creating a brand new, never before seen instance of a view controller (a navigation controller in this case.) That navigation controller has nothing to do with the one that belongs to the current tab that you are trying to dismiss. It doesn't have anything in it's navigation stack other than the root view controller that is defined in the storyboard.
What you need to do is find the navigation controller of the current tab in your tab bar controller's tabBarController(_:shouldSelect:) method, and pass that navigation controller to your alertWasDismissed closure.
At the time the tabBarController(_:shouldSelect:) method is called, the tab bar controller's selectedViewController should contain the current view controller. Replace the line above with:
if let navContr = tabBarController.selectedViewController? as? UINavigationController {}
That should work.

How to embed a view controller into a navigation view controller programmatically

I am trying to embed my view controller into a navigation view controller so i get the navigation bar and all the other stuff like back buttons. I want to do it programmatically.
It is done like this:
// example ViewController
let myVC = UIViewController()
// create the NavigationController with my VC as root
let navCon = UINavigationController(rootViewController: myVC)

How to make transparent to second View controller using Swift

I have really trouble to make transparent a view controller. I have 2 view controller. and trying to make transparent second view controller.
This is my first view controller.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let destViewController : SearchViewController = storyboard.instantiateViewController(withIdentifier: "SearchViewController") as! SearchViewController
destViewController.getSearchTxt = self.tagsData[indexPath.row]
// destViewController.modalPresentationStyle = .currentContext
destViewController.modalPresentationStyle = .overCurrentContext
self.navigationController!.pushViewController(destViewController, animated: true)
this is my second view controller.
self.view.isOpaque = false
self.view.backgroundColor = .clear
black background is displaying instead of trasparent
For UINavigationController displaying .overCurrentContext is impossible. If you want to display it overCurrentContext use present
self.present(destViewController, animated: true)
If pushViewController is really required you can try to save the previous view to image and add it as a subview to the new SearchViewController.view.

How to present a view controller inside a navigation controller SWIFT

I have VC1 which is a basic view controller, I then want to present VC2 which is inside a navigation controller. Whenever I present it, it doesn't display the navigation controller. I want this all done pragmatically. The code I have been using to present VC2 is:
func matchesPressed(sender: UIButton!) {
let matchesTVC: Matches = self.storyboard?.instantiateViewControllerWithIdentifier("Matches") as! Matches
self.presentViewController(matchesTVC, animated: true, completion: nil)
}
How do I present the navigation controller it is inside as well?
Is the navigation controller in the storyboard? If so, give it a storyboard ID and replace your matchesTVC stuff with the navigation controller.
If matches is a standalone view controller in the storyboard, you can do it in code like this:
let matchesTVC: Matches = self.storyboard?.instantiateViewControllerWithIdentifier("Matches") as! Matches
let navContr = UINavigationController(rootViewController:matchesTVC)
self.presentViewController(navContr, animated: true, completion: nil)
Instantiate the navigation controller that contains your view controller and present the navigation controller.