3

This has been driving me nuts for almost 2 days now. I've tried just about everything, and can't get any results. Every post that addresses unwinding, doesn't seem to specifically address unwinding back to a ViewController in a different storyboard, let alone doing it programmatically. What am I doing wrong?????

I have two ViewControllers that reside in different storyboards...

I want to unwind from my SignupViewController located in my Signup storyboard to my LoginViewController located in my Login storyboard. I want to perform the unwind programmatically after the user successfully registers, receives a confirmation alert with an OK button, and clicks the OK button.

This is where I want to unwind from => to

enter image description here

This is how I am attempting to do it

So I create an unwindToLoginViewController action method in my LoginViewController.swift file like so...

enter image description here

And create a reference to it in my SignupViewController.swift file like so...

enter image description here

Subsequently, I get the reference as expected...

enter image description here

And set the Identifier in the same, so I can reference it in my code...

enter image description here

When I run my app, successfully register a user, I display a confirmation alert with an OK button. When the user clicks the OK button, I want to unwind to my LoginViewController, but NOTHING happens...

Any clues?????????

enter image description here

gangelo
  • 3,034
  • 4
  • 29
  • 43
  • @Morits - who's "yelling?" I am emphasizing, but thank you for the extra tags :) – gangelo Sep 29 '17 at 16:20
  • 1
    Result of a quick test: no problem unwinding to a View Controller in a different Storyboard... so there must be something else going on in your code. Are you sure that line is being reached? If so, are you sure `self` at that point is referring to the proper context? – DonMag Sep 29 '17 at 16:43
  • @DonMag I'm sure the code is being reached, as I hit the break point I set. self is referring to the proper SignupViewController VC :S – gangelo Sep 29 '17 at 16:51
  • It works for my quick test also, are you sure `LoginViewController` is on the navigation stack? – chengsam Sep 29 '17 at 16:58
  • @chengsam LoginViewController up to the point of trying to unwind to it has not been viewed or instantiated if that's what you're referring to. – gangelo Sep 29 '17 at 17:05
  • @gangelo Unwind segue is for popping to previous view controller, if it has not been instantiated before you probably want a push segue. – chengsam Sep 29 '17 at 17:23
  • @Rob I've presented 5 VC's up to, and including SignupViewController (none of which was LoginViewController). What I'm looking to do, is present LoginViewController, but FORGET about all my previous navigation, for example, remove all the other VC's because they will never be returned to or needed after the user is registered. Unwind removes all those previous VC's from the navigation stack which is what I want. How do I present LoginViewController AND clear the navigation stack without using unwind? – gangelo Sep 29 '17 at 17:34
  • @gangelo - are you in a `UINavigationController` stack at the point where you want to "FORGET about" your previous navigation? – DonMag Sep 29 '17 at 17:50
  • @DonMag The Storyboard SignupViewController is part of uses UINavigationController and I'm calling self.performSegue(withIdentifier: "unwindToLoginViewController", sender: self) from SignupViewController. – gangelo Sep 29 '17 at 17:52
  • 2
    @gangelo - OK - well, couple options that might work for you... 1) use "swap root view controller" approach, as ref'd by Rob, or 2) start at `LoginViewController` and immediately "auto-show" the 1st VC in the Signup process. Then you can "unwind" to Login and "forget" all the others. – DonMag Sep 29 '17 at 18:01

1 Answers1

5

Unwind segues should only be used to unwind back to a view controller that already has been presented and is still in the view controller hierarchy.

In comments, above, it's clear that this is not the case. It would appear that your intent is to dismiss everything currently in the view hierarchy and replace it with a completely different scene (a login scene in your example). In that case, you should just replace the root view controller with something like (as shown in https://stackoverflow.com/a/41144822/1271826):

let window = UIApplication.shared.keyWindow!
let frame = window.rootViewController!.view.frame

let controller = UIStoryboard(name: "Login", bundle: nil)
    .instantiateViewController(withIdentifier: "...")!

controller.view.frame = frame

UIView.transition(with: window, duration: 0.3, options: .transitionCrossDissolve, animations: {
    window.rootViewController = controller
}, completion: { completed in
    // maybe do something here
})

But let's assume for a second that you did want to use an unwind segue because you thought the view controller would be in the view hierarchy. (I know that's not the case here, but for the sake of future readers, I'll going to explore this scenario.)

Bottom line, if an unwind segue ever fails, you should first confirm that the view controller with the unwind IBAction actually is in the view controller hierarchy.

If you're ever unsure about the view controller hierarchy, pause execution of your app and print the hierarchy:

(lldb) expr -l objc++ -O -- [UIViewController _printHierarchy] 
<UINavigationController 0x7ff341047800>, state: appeared, view: <UILayoutContainerView 0x7ff340f15610>
   | <MyApp.FirstViewController 0x7ff340c1d2f0>, state: disappeared, view: <UIView 0x7ff340c336a0> not in the window
   | <MyApp.SecondViewController 0x7ff340d08880>, state: disappeared, view: <UIView 0x7ff340d09620> not in the window
   | <MyApp.ThirdViewController 0x7ff3433089d0>, state: disappeared, view: <UIView 0x7ff343104b80> not in the window
   | <MyApp.FourthViewController 0x7ff343102810>, state: disappeared, view: <UIView 0x7ff340d0b150> not in the window
   | <MyApp.FifthViewController 0x7ff340f19c60>, state: appeared, view: <UIView 0x7ff340d02010>

Just make sure that the view controller with the unwind action is shown in the hierarchy.

Bottom line, you can only unwind to something currently in the view controller hierarchy, so make sure it's there.

chengsam
  • 7,315
  • 6
  • 30
  • 38
Rob
  • 415,655
  • 72
  • 787
  • 1,044