How to embed a UINavigationController in prepareForSegue? - ios

Currently I have a VC1 of type UITableViewController that is embedded in UINavigationController. When the user selects a cell, it performs a push segue to VC2 also of type UITableViewController. That is fine because the navigation bar is still present.
However in VC1, there is a UIBarButtonItem in the navigation bar, that upon tapped, also segues to VC2 and performs different things, but it uses all the same menu layout.
Using the UIBarButtonItem to segue to VC2, I like to perform a modal segue to distinguish between the two actions.
I know that modal segues encompasses the whole screen, and any top bars will be removed.
I followed this question: Modal segue, navigation bar dissapears
One of the answers provided shows how to embed a UINavigationController in prepareForSegue, so I followed it and implemented:
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "AddSegue"
{
let navigationController: UINavigationController = segue.destination as! UINavigationController
var addVC: VC2 = VC2()
addVC = navigationController.viewControllers[0] as! VC2
}
}
However, I get the error:
Could not cast value of type 'VC2' to
'UINavigationController'
How can I properly embed a UINavigationController in prepareForSegue because I need to pass data between different view controllers.
Here's my storyboard:

The segue you're intersecting is to your VC2, not a navigation controller. You're going to need to update the "AddSegue" segue to point to a navigation controller, then link your VC2 as the root view controller of the navigation controller.
If you post your storyboard, I can give you more details on how to do this.
EDIT: Here's how you should set up your storyboard. It might get a bit weird, since VC2 has two parent navigation controllers, but it should be fine.

Related

View pops from navigation controller stack when tapped

I have a popover view which is simply a stack of UIButtons.
The popover is presented from a view controller (Records) which is itself inside a NavigationController.
I need the buttons in popover view to be able to push other views on top of the navigation stack.
Here's how I prepare the segue for the popover in the Records view controller:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "popoverSegue" {
let dest = segue.destination as! PopoverViewController
dest.navController = navigationController
dest.modalPresentationStyle = .popover
dest.popoverPresentationController?.barButtonItem = addButton
dest.popoverPresentationController?.delegate = self
}
}
Then inside the popoverViewController I got a bunch of IBAction functions where I need to push other views on top of the navController that was set above.
let editor = EditorViewController(nibName: "EditorViewController", bundle: nil)
navController?.pushViewController(editor, animated: true)
This kina works and the editor view shows up with a nav bar and all, but as soon as I tap on the view or try to scroll, it just gets dismissed.
How can I prevent that dismiss thing? I did try setting isModalInPresentation. It didn't work for me.
Answering, as per OP's comments...
The proper approach is to have your "popover" controller tell the presenting controller to push a new VC onto the navigation stack.
This can be done in a few different ways, but most commonly by using either the protocol/delegate pattern or with closures.

How I could clean UINavigationBar transitions history?

I currently have parental "menu" TableView with UINavigationBar and from each cell there is a segues by reference outlet to 3 similar Views with different information.
In each View there is a buttons to other 2 Views.
With every button's segue opens another View.
The problem:
From every View UINavigationBar's back button returns me to previous View but i tries to make back button to "menu".
Additional Bar Button Item and segue from it makes very close effect but segue animation is not like in UINavigationController.
How I could clean UINavigationBar transitions history in segue to initial View?
You can try pop to root view controller or You can edit navigation controller viewControllers property and remove/add some VC in between.
You can try Unwind Segue mechanism too.
Here are some methods(function) that navigation controller providing for pop operations. They are returning optional UIViewController (intance) from it’s navigation stack, that is popped.
open func popViewController(animated: Bool) -> UIViewController? // Returns the popped controller.
open func popToViewController(_ viewController: UIViewController, animated: Bool) -> [UIViewController]? // Pops view controllers until the one specified is on top. Returns the popped controllers.
open func popToRootViewController(animated: Bool) -> [UIViewController]?
Here is sample code as a solution to your query::
// if you want to back to root of your app
if let rootNavigationController = self.window?.rootViewController as? UINavigationController {
rootNavigationController.popToRootViewControllerAnimated(true)
}
// But if you want to back to root of your current navigation
if let viewcontroller = self.storyboard?.instantiateViewController(withIdentifier: "NewViewController") as? NewViewController { // or instantiate view controller using any other method
viewcontroller.navigationController?.popToRootViewControllerAnimated(true)
}

Swift - TabBarController -> ViewController -> NavigationController

i have the following situation:
I got a TabBarController with some tabs(ViewControllers).
When i am in one of these ViewControllers, i tap a button and i want to segue to a NavigationController AND still see the tabbar...
Here is what i did:
I created a new ViewController(DetailViewController)
I embedded this new ViewController(DetailViewController) in a NavigationController
I created a segue(Show) from the "viewcontroller which is embedded in the tabbarcontroller" to the "new navigationcontroller"
I coded:
func buttonTapped {
performSegue(withIdentifier: "shownavicontroller", sender: nil
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationNavigationController = segue.destination as! UINavigationController
let targetController = destinationNavigationController.topViewController as! DetailViewController
}
What goes wrong:
NavigationController is sliding from bottom to top... it should slide from left to right
BackButton in NavigationController is missing
TabBar in NavigationController is missing...
Anybody could help me with this issue?
Thanks and Greetings!!
You have done wrong.
You should not embed UIViewController directly to tabBarController to get the desired result you want.
From Storybaord,
If you are designing your application from storyboard then you should add a UIViewController and embed this UIViewController object into UINavigationController and then embed this NavigationController in a UITabBarController. So that if a button in above UIViewController is pressed and you need to open an other UIViewController not form Bottom to Top but from Left to Right and expecting a Automatic back button at top bar and hide bottom bar.
Then you need to create a Push/Show Segue form Above ViewController (Embed in NavigationController -> Embed in TabBarController) to you new UIViewController that will open.
And before calling the push/show segue you need to write bellow lines.
self.tabBarController?.hidesBottomBarWhenPushed = true
According to your question i believe this is what you need:

Unwind from OverCurrentContext modal presentation doesn't work

I am having a problem similar to this:
Cannot Get Unwind Segue Working with Modal View Controller Presented Over Current Context
I presented a VC modally using OverCurrentContext presentation style following a tutorial. All set in storyboard.
VC1 -> modally overCurrentContext -> VC2
The problem is that Xcode 8 has slightly different options in the Attributes Inspector, no OverCurrentContext option in the Segue, so I had to select the presentation: default in the Segue
and set the presentation: overCurrentContext in the VC2
Now, when I try to unwind back to the VC1 I can't, nothing happens and I get stuck in VC2.
I had to add some extra code to the unwind method to make this work.
#IBAction func unwindFromAdvancedOptions(segue: UIStoryboardSegue) {
if segue.source as? VC2 != nil {
segue.source.dismiss(animated: true, completion: nil)
}
}
But I'd really like to understand why storyboard settings where enough to unwind any other modal presentation styles but OverCurrentContext.

Show Segue from button opens without navigation controller

I have two view controllers and a Navigation contoller in a storyboard. In the first view controller I have two buttons.
Both buttons segue to the second view which contains a map and opens the map with different info. They are both of the kind show.
The first button when clicked opens the map with the navigation bar at the top (it loads from the side).
The second button loads the map without the navigation bar (it loads from the bottom).
I want both buttons to load the map with the navigation bar.
I am using xcode 7.3 swift and storyboards
Also using prepare for segue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "lav"){
let DestViewController = segue.destinationViewController as! MapView
DestViewController.type = typeLav
}
if(segue.identifier == "cam"){
let DestViewController = segue.destinationViewController as! MapView
DestViewController.type = typeCam
}
}
Set the segue action
Present Modally
Show Up from bottom, and without navigation controller, so there is no navbar too.
Push
Push the view controller to current navigation stack, so the navigation bar is shown
btw, method prepareForSegue was used to setup data transfered between view controllers;

Resources