Why is my unwind segue crashing my app? - ios

I am trying to create an unwind segue that takes me back two viewControllers, and I thought I had everything set up correctly, but it crashes with no error printed when I perform the segue...
Here's what I've done:
In the DESTINATION viewController, we'll call it VC1 (bottom of the stack) I created this action:
#IBAction func unwind(segue:UIStoryboardSegue){}
In the interface builder I hooked up VC3 (the third view controller up) to the unwind segue via the exit button and named it "unwind".
I call perform for segue like so:
performSegue(withIdentifier: "unwind", sender: self)
Here is the view controllers and segue identifier
http://imgur.com/a/gJPYQ
The "Delete Trip" button calls the segue AFTER all the other logic has been taken care of.
As soon as that is called, my app crashes with no error message and shows me the AppDelegate screen. What's going on?

If you pushed your VC, you could use:
navigationController?.popToRootViewControllerAnimated(true)

If you have two VC's presented modally, then you will need to dismiss two VC's modally. Use:
dismiss(..., completion: {
dismiss(..., completion: nil)
Your current "unwind" segue is simply presenting the original one again..and maybe you don't have identifiers set up correctly or you are overlooking your view hierarchy.

Related

"no segue with identifier" when using 'Unwind Segue' with a storyboard reference

I've followed the instructions here and here which suggest that I should be able to create an unwind/edit segue even when using a storyboard reference.
The flow is quite simple:
PhotoDetailScene has a storyboard reference to EditHistoryScene and a tap gesture to trigger the segue, then I have a close button on EditHistoryScene that unwinds back to PhotoDetailScene. The present works fine (the custom 'show' segue opens the EditHistoryScene), and if I use a dismiss() call it dismisses fine. But unwinding with the segue identifier always fails with:
EditHistoryScene has no segue with identifier 'UnwindEditHistorySegue'
In my EditHistoryScene close button action, I have:
func closeButtonPressed(_ sender: Any)
performSegue(withIdentifier: "UnwindEditHistorySegue", sender: self)
}
And in my PhotoDetailScene, I have added:
#IBAction func unwindToPhotoDetailScene(_ unwindSegue: UIStoryboardSegue) {
print("It works!")
}
And here's how I've set it up in IB, with the unwindToPhotoDetailScene() method connected to the storyboard reference (since that's the only way IB would let me ctrl+link the outlet):
Presenting segue:
Unwind segue properties (and segue name)
Storyboard reference correctly set for destination storyboard:
Storyboard reference's exit point connected back to PhotoDetailScene:
EditHistoryScene storyboard instance appears to not be connected to the #IBOutlet?
My best guess is that it's failing because this is a storyboard reference, and the unwind segue is defined on the reference, not the actual storyboard instance. But I can't figure out how to attach the EditHistoryScene's exit point to the PhotoDetailScene directly.
You don't need to create any segues to the reference itself.
Once your second storyboard contains a reference to the first storyboard, any unwind functions defined in the first storyboard are available.
You create exit segues by dragging from the exit trigger to the exit icon in the view controller scene.
If you want to trigger the unwind from your "close" button, simply ctrl-drag from the close button to the "exit" icon at the top of its view controller and you will see unwindToPhotoDetailScene as an option.
You only need to give the segue an identifier if you want to trigger it programatically.
For example, you might want an action handler function on the close button that checks to see if there are unsaved changes. If there are, prompt the user to confirm that they will lose their changes (or to save or whatever). Once they are happy to proceed you can the invoke the unwind.
To set this up, ctrl-drag from the view controller object to its own exit icon. Create the unwind segue and give it an identifier.

Unwind segue (still) not working

I'm trying to get an unwind segue working (in Swift) and have read through all the "unwind segue not working" posts I could find but haven't yet found whatever it is I'm doing wrong. So.
I have a UISplitViewController with a UITableViewController as my left-hand menu and two UINavigationController+UITableViewController detail views that I'm switching between. Segue-based navigation from my left-hand menu works fine. It's when I want to programmatically unwind that things do not.
I've created an #IBAction function in my first view controller, the one I want to unwind to, like this:
#IBAction func unwindToDocuments(_ segue: UIStoryboardSegue) {
}
(My first view controller is my "Documents" view.)
Then, in the second view controller, I connect an unwind segue to the exit node with identifier unwindSegueToDocuments and action unwindToDocumentsWithSegue:.
It's my understanding that should be all I need to do. However, when I try:
self.performSegue(withIdentifier: "unwindSegueToDocuments", sender: self)
it doesn't do anything. It stays in my second view controller as the detail view.
I'm using self.performSegue there because I'm in a closure. It's some network work so it's being done in a DispatchQueue.async() background queue. However, the performSegue call is in a nested DispatchQueue.main.async() block at the end. (Or, rather, I've tried it both/all ways, and still can't get it to unwind.)
Nothing helpful appears in the console.

Unwind not going to the right viewcontroller

I am trying to use an unwind segue to logout from my app.
Here is my view hierarchy:
MainVC->(show)->ConnectionVC->(show)->HomeTabBarVC->SettingsVC (4th tab of the HomeTabBarVC containing a tableview)
MainVC, ConnectionVC and HomeTabBarVC are in three different Storyboards.
When pressing the "Disconnect" row of SettingsVC, I want to unwind to MainVC.
I already tried to follow this:
What are unwind segues and how do you use them?
and
Unwind segue and nav button items not triggering after tab bar controller added
The unwindToThisViewController function (which I put in MainVC) from the tutorial is triggered but the only thing that happens is going back to the first tab of HomeTabBarVC.
I tried to execute this action in SettingsVC in two ways:
(self.tabBarController! as! HomeTabBarVC).performSegue(withIdentifier: "unwindToMainVC", sender: self)
and
self.performSegue(withIdentifier: "unwindToMainVC", sender: self)
Neither are working...
Any toughts?
You can do this without using unwind segues. Just use popToRootViewController:
navigationController?.popToRootViewController(animated: true)
I found a solution : after seeing that I had the "Presenting view controllers on detached view controllers is discouraged " warning, I created a Delegate to execute the segue in my HomeTabBarVC and it works fine! Thanks everyone for your help!!

ViewController object recreated after navigate back?

Now I created a new project to test unwind segue.
In Storyboard the story entry is on VC0, a button in VC0 goes to VC1 (modally), a button in VC1 goes to VC2 (modally).
VC2 has a button to dismiss itself and in the function it looks like this:
#IBAction func btnDismiss(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
in VC1 I added an unwind function as follows:
#IBAction func unwindSecondView(segue: UIStoryboardSegue){
print("unwinded")
}
Then in storyboard I linked VC2's exit icon to unwindSecondview as action.
It works pretty well, however after I clicked "dismiss" button in VC2, VC1 appeared briefly and jumped back to VC0.
??? Anything wrong that caused jumping back to VC0?
--------------Initial question -----------------
I'm new to iOS and got a little confused for how VCs are created and activated.
Say I created 2 ViewControllers in my single view app. MainController(VC_M) and SettingsController(VC_S). I added the segues in storyboard, a setting button in VC_M goes to VC_S, VCS collects information, writes to standardDefaults, then ok button goes back to VC_M and refresh its view.
When I try to preserve some information in VC_M, I found that after I click ok button in VC_S and go back to VC_M, VC_M gets recreated and viewDidLoad() gets called. In the debugger, it shows the VC_M object (self) now has a different address in memory, so seems it's another instance of the class.
Is this a normal behavior? It's best that the old VC_M object gets saved so some data doesn't need to be reloaded. Initially I thought I could put some data loading stuff in init(), but when VC_M gets re-created init() got called, too. Some older posts suggested that ViewDidLoad() should not be called again but rather ViewDidAppear() should get called, but I'm not sure if it's the same case now.
In my case is it better to just use standardDefaults to reload everything, or is there a different kind of segue I should use? (I used push segue).

Returns to orginal view after segue

I have a view controller, after a button is pressed I want it to unwind to the original table view controller and then let it segue into another view controller.
I don't segue directly to the new view controller because I want that when the back button gets pressed it returns to the original table view controller.
But when I do this it loads the view controller where it's supposed to end, but directly after that it directly returns to the original table view controller
This is my setup in storyboard:
http://imgur.com/dcvvxi5
And this is the code I use to make it happen.
I call this code in the view controller where the button gets pressed:
self.performSegueWithIdentifier("unwindChooseHome", sender: nil)
And this code inside the original table view controller:
#IBAction func unwindChooseHome(segue: UIStoryboardSegue) {
self.performSegueWithIdentifier("destination", sender: nil)
}
Hopefully you understand my question I am not native. I don't really know what I am doing wrong maybe there's a totally different way to make this happen.
Thanks in advance :)
I imagine that the problem is that you're triggering the "destination" segue prior to the completion of the unwind segue.
Instead of triggering the "destination" segue immediately inside of the unwind action method, try setting a flag on the original view controller that you can then check in viewDidAppear: and trigger the segue at that point.

Resources