Unwind Segue Between Two View Controllers Back and Forth Swift - ios

I am looking to build an app with two view controllers (VC1 and VC2) that each contain a timer. I would like for my user to be able to switch back and forth between these views and allow each timer to still run.
Currently, I have been successful in unwinding to either VC1 or VC2 (depending on which I set as the initial view controller), though I am having difficulty in successfully unwinding back and forth (i.e. from VC1 to VC2 back to VC1 and etc.)
I figured I might be able to accomplish this by initially segueing from VC1 to VC2 with a normal segue (from a button press), and though it will unwind back to VC1, I cannot get my app to unwind back to VC2 from here.
My two simple timer view controllers
Here is the code (for VC1):
#IBAction func unwindToSecondView(_ sender: UISwipeGestureRecognizer)
{
performSegue(withIdentifier: "unwindToSecond", sender: self)
}
#IBAction func backFromSecondView(segue: UIStoryboardSegue) {
}
And for VC2:
#IBAction func segueToFirstView(_ sender: UISwipeGestureRecognizer)
{
performSegue(withIdentifier: "unwindToFirst", sender: self)
}
#IBAction func backFromFirstView(segue: UIStoryboardSegue) {
}
I am really new to swift, and have found a couple interesting sources on here (How to unwind two view controllers and Swift Timer() will not update label after switching between views) but have not had much success otherwise -- would really appreciate any advice or ideas for different implementations. Thanks!!

Apple has published good example for that. I recommend always check Apple Developer Guide sites and source code. Your answer below. https://developer.apple.com/library/content/samplecode/SegueCatalog/Introduction/Intro.html

I found this tutorial useful.
working-with-unwind-segues-programmatically-in-swift

segue from A-B and from B-A you can just dismiss() and if you want to send data back from B-A you can create a delegate.

Related

What's wrong with my segue code in Swift?

I'm trying to segue into a 'settings' View Controller by clicking a button, and I'm assembling it via code but don't know what I'm doing wrong.
This is my button code:
#IBAction func settingsButton(_ sender: UIButton) {
self.performSegue(withIdentifier: "SettingsViewController", sender: self)
}
The View Controller is called 'Settings View Controller' (unsurprisingly). The app crashes whenever I press on it in my Simulator.
It'll probably be a simple thing, but any ideas what I'm doing wrong?
You must set your segue identifier whatever you want (for your question = SettingsViewController) from storyboard :
Hope it helps...

View Controller get stuck on calling unwind segue in Swift

I have a bit complex hierarchy of calling multiple VC's and then at the end unwind to particular VC again, My flow is like this,
I have a VC that opens with these two conditions,
HomeVC -> DetailVC -> VC1 -> An API call to check if data exist, if yes then present ListVC if not then present Form VC
If FormVC is opened then after submitting form i have to show ListVC
If ListVC is opened first then it simply present Form VC, as in UI ListVC comes first and FormVC is the second one.
Now when i comes directly from FormVC to DetailVCthrough unwind segue, detail vc screen get stuck, now action is performed on it neither it scrolls. I'm too much confused why it is showing such behaviour. How i can fix it? why it is stuck my app?
This is how i call Unwind segue in DetailVC,
#IBAction func unwindToPropertyDetail(sender: UIStoryboardSegue)
{
}
and in FormVC, I just performSegue method like this to come on DetailVC,
self.performSegue(withIdentifier: "GoToDetails", sender: self)
Have you try using dispatch queue?

Go back to previous page using unwind segue

I wanted to just go back to my previous page
from Attendance in going to Leave and Leave back to Attendance
LeaveViewController.swift
#IBAction func LeaveAttendanceSequeConnect(_ sender: Any) {
performSegue(withIdentifier: "LeaveAttendanceSegue", sender: nil)
}
Attendance.swift
#IBAction func LeaveUnwindSeque(segue: UIStoryboardSegue){
}
and then on my Leave Scene
I have ctrl drag to Exit
Pressing the Back button in Leave wont go back to Attendance
The segue should work without needing another segue to leave the unwind. Try this:
1) Keep your original LeaveAttendanceSequeConnect (which should have been bound with ctrl drag from your view controller in story board over to your corresponding .swift file).
2)Get rid of the LeaveUnwindSeque code and unbind that rewind segue properly by deleting the segue (p.s. is segue with a "g" not seque). Now click on the segue connection of the LeaveAttendanceSequeConnect in the storyboard. Make sure the original navigation controller has attributes and looks the same on the storyboard like figures A) and then make sure your second segue has attributes/storyboard like figure B).
A attribute:
B attribute:
B storyboard:
A: storyboard:
The signature of the unwind is incorrect.
#IBAction func LeaveUnwindSeque(segue: UIStoryboardSegue){
}
replace with
#IBAction func LeaveUnwindSeque(_ segue: UIStoryboardSegue){
}

dismiss two controllers Swift

I have this situation :
I have a first view controller , when tap on button in it I open in modal mode another view controller , in this view controller when I tap another button I open in modal view another view controller and in it there is a button and when I tap on it I want to go to first view controller without re-initialize it.
How do I do it?
This is the perfect situation for an unwind segue.
Put this in your first viewController (the one you want to return to):
#IBAction func backFromVC3(_ segue: UIStoryboardSegue) {
print("We are back in VC1!")
}
Then in the Storyboard in your 3rd viewController, control-drag from your button to the exit icon at the top of the viewController and choose backFromVC3 from the pop-up.
Now, when the user presses the button in VC3, both VC3 and VC2 will be dismissed and you will return to VC1.
If you are not using Storyboards, you can dismiss the viewControllers with code. Here is code for a button's handler to dismiss two levels of viewController:
func doDismiss(_ sender: UIButton) {
// Use presentingViewController twice to go back two levels and call
// dismissViewController to dismiss both viewControllers.
self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)
}
Thanks all for reply and edited my question :)
I found 2 line code to resolved my problem:
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window!.rootViewController?.dismissViewControllerAnimated(true, completion: nil).
And that work well.
Thanks very much

Unwind segue - going back multiple views

Lets say I have 3 ViewControllers - A, B and C. A shows B, B shows C. Then I want to go back to A without going through (visually) B (like home button). My problem currently is that when I unwind to A, for short period of time B is shown (viewWillAppear and etc. methods are called). How can I resolve this?
Note1: The above example is highly simplified compared to my real app navigation tree and for me using NavigationController as container to all A,B and C is not possible (or at least not desirable). Few of the reasons are in the middle of the transition there are complex embed segues and different custom transition(almost all animated transitions are absolutely different) across all views.
Note2: I found some pseudo solution with defining custom segue and using it as a Custom Unwind Segue. That is not desirable too because I want to use my already done transition animators.
Any help is highly appreciated.
Please note that this is an amended answer - in response to the first comment below.
I have a possible solution which seems to work. But it may not be appropriate. I am not certain and offer it for consideration only.
The 3 view controllers are set up as described in the question (the second is red in order for me to notice whether it is visible during the unwind).
The unwind segue is created in the third view controller (C) by dragging to the Exit. Before doing this the required actions have to be added to the first and second view controllers.
Below is the code for the 3 view controllers. My fix - I am using a a global boolean called unwindCheck as a flag which is set true before the unwind but is otherwise false. If it is true then self.view.hidden = true in viewWillAppear for the second view controller. ie hidden during the unwind.
Please note that I have also added a second button on the third view controller - it calls the same unwind segue - the identifier property of which is set to "UnwindToFirstSegue". The second button is not a necessary part of this possible solution.
class FirstViewController: UIViewController {
#IBAction func unwindToFirstViewController(segue: UIStoryboardSegue) {
}
override func viewDidLayoutSubviews() {
unwindCheck = false
}
}
class SecondViewController: UIViewController {
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if unwindCheck == true {
self.view.hidden = true
}
}
#IBAction func unwindToSecondViewController(segue: UIStoryboardSegue) {
}
}
class ThirdViewController: UIViewController {
#IBAction func backToA(sender: AnyObject) {
performSegueWithIdentifier("UnwindToFirstSegue", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let identifier = segue.identifier{
switch identifier {
case "UnwindToFirstSegue":
unwindCheck = true
default:
break
}
}
}
}
The unwind segue's identifier can be set by selecting it in the Document Outline and then going to the Attributes inspector.

Resources