how to unwind segue to the view controller that called it - ios

Below is a great answer of how to use Apple's unwind segue.
What are Unwind segues for and how do you use them?
My problem with the answer however is that you have to explicitly tell storyboard which view controller you want to exit (unwind) back to. What I'm trying to do is exit (unwind) back to whichever view controller called it, only using one button.
Let's say I have 3 view controllers: Red, Blue, and Yellow.
Both Red and Blue have a button on them to go to the Yellow view controller, but Yellow only has one button, return. Is it possible to have the yellow return button unwind back to whichever view controller called it?

thanks to #luk2302 I was able to figure it out. No need to even use unwind segue. Thanks luk2302!
#IBAction func returnViewController(sender: AnyObject) {
if((self.presentingViewController) != nil){
self.dismissViewControllerAnimated(true, completion: nil)
}
}

Related

How to segue from tab bar view controller to another view which is a child of a navigation controller

I laid out my home screen (Summary screen) as shown on the screenshot below:
I added the "+" button on the UITabBarController subclass. This button will segue to a view controller and show it modally. To give you a bit of context on how I've structured my storyboards, please refer to the screenshot below:
This modal view controller has a form that the user needs to fill in, and once they're done, there's a 'Done' button which will 1) dismiss the modal, 2) take them back to the root view which is either the 'Summary' tab or the 'Details' tab then 3) take them to a list view showing the most recent data they've entered on a list (destination view – highlighted in red).
Now, doing the segue when the user taps the "+" button is simple enough. With the following code:"
menuButton.addTarget(self, action: #selector(menuButtonAction(sender:)), for: .touchUpInside)
then
func addNewExpense(action: UIAlertAction){
self.performSegue(withIdentifier: "segue_formModal", sender: self)
}
On the modal I've setup a protocol which will then send the form data back to the tab view controller.
extension XtabBarViewController: NewInfoDelegate{
func newInfoSubmitted(formData: FormData) {
performSegue(withIdentifier: "segue_ListingPage", sender: self)
}
}
But it seems that the perform segue is not working. It says the segue does not exist. "segue_ListingPage" is that segue that connects the Summary view and the destination view.
How can I segue from the tab bar view controller to the destination view? Any help is appreciated.
Thanks in advance!
You can just make the navigation view controller the entry point.
I figured it out on my own. For the benefit of those who run into the same issue here's my solution.
I simply added the code from the tab bar view controller the code:
let childVC = children[0].children[0]
childVC.performSegue(withIdentifier: "segue_TXListPage", sender: self)
So what I did here is call the performSegue from the view controller that segues to the destination controller.

Double return to previous view - Swift

I'm new with IOS and Swift so don't judge if solution is easy.
I have three ViewControllers like A,B and C.
I started from A -> NavigationController -> B -> NavigationController -> C
In specific situation I need to come back from C to A without seeing B. Is any way to do this?
Maybe changing the parent navigationController? Maybe I can print stack with every current view? - it will be really helpful.
I tried dismiss C and B view one by one and it work's but then we can see B view for a moment - so it's not a solution for me.
P.s : I'm using Modal kind to switch between controllers.
enter image description here
If A is always the first view controller, you can just do :
viewcontrollerC.navigationController?.popToRootViewController(animated: true)
This methods pop the stack to the first view controller, without displaying intermediates ones
If A is not the first viewController, you can do :
viewcontrollerC.navigationController?. popToViewController(viewControllerA, animated: true)
If you don't have a reference to viewControllerA, search it in the stack :
let viewControllerA: UIViewController?
for (let vc in (self.navigationController?.viewControllers ?? [])) {
//adust the test to find the appropriate controller
if vc.isKindOf(ViewControllerAClass.self) {
viewControllerA = vc
break
}
}
if let viewControllerA = viewControllerA {
self.navigationController?.popToViewController(viewControllerA, animated: true)
}
source : https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621871-poptoviewcontroller
There are 2 ways you can achieve this. The simple to implement is in View Controller C you can, on in the specific situation, invoke following function:
navigationController?.popToRootViewController(animated: true)
This will pop all the navigational view hierarchy and take you back to the root i.e. the first view controller.
Second approach is to define unwind method in the view controller you want to go back to. In view controller when you start typing unwind, in Xcode 10 you will get autocomplete to add this Swift Unwind Segue Method.
#IBAction func unwindToA(_ unwindSegue: UIStoryboardSegue) {
let sourceViewController = unwindSegue.source
// Use data from the view controller which initiated the unwind segue
}
In this particular question let us say you added this method in View Controller A as you want to go back to it. I assume you have a button on View Controller C to go back to A. Controll+Drag from the button to the Exit symbol of the view controller A. The unwindToA method will automatically pop-up. Connect to it and you are done. When the user presses this button it will go back 2 navigation controllers to A.
Note: By this method you can go back to any navigation controller on the Navigation stack and it is not limited to root view controller alone. Below I am addition picture showing the exit on a view controller.

Swift: performSegueWithIdentifier during unwind not working

I've created a typical unwind flow from my view controller #2 to back to view controller #1 using a programmatically created button using the segue to Exit technique.
I have trace statements that confirm that the button code is executing perfectly and that the #2 performSegueWithIdentifier func is being called with the correct segue ID, but nothing happens.
To clarify:
I've connect the view controller #2 to the Exit and confirmed the segue ID is exact in all places. I traced the #2 identifier in the #2 performSegueWithIdentifier func and it matches perfectly.
As I understand it, I no longer need to use the dispatch fix with the current version of 2016 XCode. I tried it anyway and nothing worked. There is no crash, just no unwinding.
Somehow the unwind technique isn't reversing using this Exit technique. Any ideas?
I've been following the tutorial here: https://spin.atomicobject.com/2014/12/01/program-ios-unwind-segue/
CODE VC #2:
// action func wired to button, fires perfectly
func unwind(seg:UIStoryboardSegue!) {
self.performSegueWithIdentifier("unwind", sender: self)
}
In VC1 you need a function:
#IBAction func unwindToVC1(segue:UIStoryboardSegue) {
}
Then in your storyboard ctrl drag from the yellow view controller icon to the Exit icon and select unwindToVC1: from the pop up
Give the unwind segue an identifier, say unwindToVC1
Now, in VC2, create your button touchUpInside handler:
func buttonTapped(sender:UIButton) {
self.performSegueWithIdentifier("unwindToVC1")
}
when you set up your button programatically, add this method as the action handler:
button.addTarget(self, action: "buttonTapped:", forControlEvents: .TouchUpInside)
Move the unwind function to VC1. Leave that implementation empty or perhaps put a print statement to see if its coming to that function.
Make sure that in the storyboard there is a unwind segue created with identifier "unwind"
Add a button action func buttonAction:(button:UIButton) that calls performSegueWithIdentifier("unwind"...) in VC2.
Set the buttonAction as the action for the button created programatically.

Unwind segue from navigation back button in Swift

I have a settings screen, in that I have a table cell. By clicking on that I take to another screen where user can choose an option and I want it back in the previous view controller when back button is pressed.
I can put a custom bar button item, but I want to return to the parent view controller using the back button in the navigation bar rather than with a custom button on the view.
I don't seem to be able to override the navigation back button to point it down to my unwind segue action and since the back button doesn't appear on the storyboard, I cant drag the green Exit button to it
Is it possible to unwind a push segue with the back button?
Here's my solution, based on Objective-C code from Blankarsch to this StackOverflow question: How to trap the back button event
Put this code inside the View Controller you want to trap the Back button call from:
override func didMoveToParentViewController(parent: UIViewController?) {
if (!(parent?.isEqual(self.parentViewController) ?? false)) {
println("Back Button Pressed!")
}
}
Inside of the if block, handle whatever you need to pass back. You'll also need to have a reference back to calling view controller as at this point most likely both parent and self.parentViewController are nil, so you can't navigate the View Controller tree.
Also, you might be able to get away with simply checking parent for nil as I haven't found a case where pressing the back button didn't result in parent being nil. So something like this is a bit more concise:
override func didMoveToParentViewController(parent: UIViewController?) {
if (parent == nil) {
println("Back Button Pressed!")
}
}
But I can't guarantee that will work every time.
Do the following in the view controller that has the back button
Swift 3
override func didMove(toParentViewController parent: UIViewController?) {
if !(parent?.isEqual(self.parent) ?? false) {
print("Parent view loaded")
}
super.didMove(toParentViewController: parent)
}
I tried the same and it seems that you cannot catch the standard back button's action so the solution will be to use a custom button and bind it to a segue which leads back to the previous page.
You could use some sort of delegation as you did or use a custom back button and an unwind segue.
Better even, you could handle passing data between your view controllers using a mediator:
http://cocoapatterns.com/passing-data-between-view-controllers/

How to unwind from UITabBarController to custom view

I´ve a UITabBarController in the middle of a storyboard and I want that when I push back button on UITabBarController (TabBar) sends me to View02 directly.
My sequence is:
NavigationController->UIViewController01-> UIViewController02 -> UIViewController03 -> UITabBarController -> 3 TabBarViews
Could you help me, please?
Thanks in advance,
You have to create an unwind segue. First add a method in the view controller you want to unwind to:
- (IBAction)unwindToMyViewController:(UIStoryboardSegue *)unwindSegue
{
}
Then in a view controller you want unwind from drag from the button to the green exit icon and select your action.

Resources