0

I am having difficulty saving/moving data between two view controllers. Specifically, I have a UIStepper on the second view controller that acts as a setting which changes a variable used on the first view controller. When I come back to the second view controller the stepper has returned to its default value which I set on the storyboard attribute inspector.

I believe that I need to make the UIStepper's default value equal to its new value after it was saved but I do not know how to. I am having the same problem with a segmented control where I want whatever selection is left there to save as a setting on my app.

'''

First View Controller:

var volume: Double = 12 
var speed: Double = 10

class ViewController: UIViewController {

    @IBAction func switchOver(_ sender: Any) {
    
    guard let destinationVC = storyboard?.instantiateViewController(withIdentifier: "popUpID") as? popUpViewController else {
        return
    }
    
    present(destinationVC, animated: true, completion: nil)

    }
}

Second View Controller:

@IBOutlet weak var volumeLabel: UILabel!

@IBAction func volumeStepper(_ sender: UIStepper) {
    volume = sender.value
    volumeLabel.text = String(sender.value) + " fl oz"


@IBAction func currentSpeed(_ sender: UISegmentedControl) {

    switch sender.selectedSegmentIndex {
        case 0:
            speed = 10              // takes 10 seconds 
        case 1:
            speed = 300             // takes 5 minutes 
        case 2:
            speed = 1200            // takes 20 minutes
        case 3:
            speed = 2400            // takes 40 minutes 
        default:
            speed = 10
    }
}

@IBAction func closePopUp(_ sender: Any) {      
    dismiss(animated: true, completion: nil)
}

'''

Matthew R
  • 1
  • 1
  • Add the code for both first and second view controller. Also, do you want to save the data within multiple app sessions? – PGDev Aug 31 '20 at 09:16
  • Try using UserDefaults – HHumorous Aug 31 '20 at 09:23
  • When I need to save user settings between sessions, I usually use UserDefaults. From controller to controller you could also set a global var in a singleton. – claude31 Aug 31 '20 at 09:25
  • @claude31 right now I am using global variables for this. My issue is figuring out how to use the variable and make it the new default stepper value in the code. (e.g. myStepper.value = myGlobalVariable) ? – Matthew R Aug 31 '20 at 09:33
  • @PGDev I added the code from both view controllers - saving the code or not I need to know how to initialize the stepper with the new default value – Matthew R Aug 31 '20 at 09:51
  • In viewDidload or viewDidAppear or in the IBAction for returning segue if you use unwindSegue, set the value of the stepper to the global var value. Need to see more code to be more specific. – claude31 Aug 31 '20 at 11:17
  • This question is being asked almost once a day. Just search for "pass data between viewcontrollers", like https://stackoverflow.com/questions/5210535/passing-data-between-view-controllers/5210861 – Andreas Oetjen Aug 31 '20 at 12:09
  • Try adding an @IBOutlet for the stepper as well. Then, in ViewDidLoad, set the value of the stepper to the value you want. – Nate4436271 Aug 31 '20 at 18:26

1 Answers1

0

If I understand the problem correctly I think you have two problems to solve.

  1. Somehow the second view controller needs to inform the first view controller that a change has been made. NotificationCenter is one way to do this
  2. Update value of stepper to be the saved value.

In the first view controller

class ViewController: UIViewController {

    @IBOutlet weak var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    
        if let value = UserDefaults.standard.value(forKey: "Stepper") as? Double {
            label.text = String(describing: value)
        }
        //subscribe to changes
        NotificationCenter.default.addObserver(self, selector: #selector(stepperDidChange), name: Notification.Name("stepperDidChangeValue"), object: nil)
    
    }

    // Handle Notification
    @objc func stepperDidChange() {
        if let value = UserDefaults.standard.value(forKey: "Stepper") as? Double {
            label.text = String(describing: value)
        }
    }
}

And then, in the second View Controller

class SecondViewController: UIViewController {

    @IBOutlet weak var stepper: UIStepper!
    @IBOutlet weak var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
    
        if let value = UserDefaults.standard.value(forKey: "Stepper") as? Double {
            stepper.value = value
            label.text = String(describing: value)
        }
    }

    @IBAction func didChangeStepper(_ sender: UIStepper) {
        label.text = String(describing: sender.value)

        // save the changed value to UserDefaults
        UserDefaults.standard.setValue(sender.value, forKey: "Stepper")
        //Post to Notification Center that the value has changed
        NotificationCenter.default.post(Notification.init(name: Notification.Name("stepperDidChangeValue")))
    }

}

These two views are linked by a present segue in a storyboard.

Here is a small demo I set up to demonstrate

Nate4436271
  • 860
  • 1
  • 10
  • 21