Reputation: 87
App has two View Controllers: ViewController
(this is the main View Controller that displays the majority of the app's content) and SecondViewController
(accessible via a UIButton
on ViewController
; SecondViewController
is only used to display a user's inventory, and a UIButton
within SecondViewController
allows the user to return to the original view, ViewController
). Currently, the app uses the "Show" action segue to switch between View Controllers when the user presses the appropriate UIButton
. However, after switching from ViewController
to SecondViewController
, and then pressing the UIButton
to return to ViewController
, the properties of ViewController
have been reverted to the properties that occur when the app launches (background color is changed, certain text fields appear that shouldn't).
So, how do I "save the state" of ViewController
when the user moves to SecondViewController
, so that the user resumes where they left off when they return to ViewController
?
Upvotes: 2
Views: 1265
Reputation: 117
Here is a simple example of segue and unwind that you can adapt to your problem... Assume that you have ViewController with label and a button and a SecondViewController with label and a button.
For the first ViewController...
import UIKit
//steps to receive data back from SecondViewController...
//1. create protocol in the SecondViewController (see SecondViewController code)
//2. conform to the protocol
class ViewController: UIViewController, UnwindSegue {
//3. method that gets triggred.
func dataReceived(dataSegued: String) {
labelOne.text = dataSegued
}
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var labelOne: UILabel!
var textReceived : String = ""
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBAction func btPressed(_ sender: Any) {
performSegue(withIdentifier: "goToSecondController", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToSecondController" {
let destinationVC = segue.destination as! SecondViewController
destinationVC.textSegued = textField.text!
//4. create delegate in the SecondViewController (see SecondViewController code)
//5. set ourselves up as delegate of SecondViewController
destinationVC.delegate = self
//6. then dismiss the SecondViewController (see SecondViewController code)
}
}
}
Then for your SecondViewController...
import UIKit
//1. create protocols and delegates to transfer data back
protocol UnwindSegue {
//single required method with a single parameter
func dataReceived(data:String)
}
class SecondViewController: UIViewController {
var textSegued : String?
//4. create delegate of the protocol of type CanReceive that can be a nil. If it is nil, it doesn't go anywhere when BT is pressed
var delegate : UnwindSegue?
@IBOutlet weak var label: UILabel!
@IBOutlet weak var secondTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
label.text = textSegued
}
@IBAction func btTwoPressed(_ sender: Any) {
//this is not triggered if var delegate is nil (as defined as optional)
delegate?.dataReceived(data: secondTextField.text!)
//6. dismiss the 2nd VC so you can see the fist VC
dismiss(animated: true, completion: nil)
}
}
Upvotes: 0
Reputation: 2930
What you are looking for is an unwind segue. Here's the simplest way of how to create it:
In your ViewController
(or, basically any other view controller you are willing to pop to) create an IBAction that accepts an instance of a segue (function name doesn't really matter):
@IBAction func unwindToThisVC(segue: UIStoryboardSegue) { }
In the storyboard, go to SecondViewController
, and control + drag from your UIButton
to the Exit
outlet of ViewController
and then select the IBAction
you've created in step 1:
Upvotes: 2
Reputation: 89232
The way you are doing it now (using Show from the second to get back to the first) actually brings up a third VC.
What you want to do is dismiss the second view controller.
The normal way is to implement a protocol for the second one that the first one implements and then to have a function in that protocol for the second one to let the first one know it is done.
When the function is called, the first one dismisses the second and then it will be shown again with its state intact.
Upvotes: 0