iosswiftuinavigationcontrolleruistoryboardsegue

How to pass variable data in view controllers embedded in a navigation stack?


Currently, I have three view controllers in my navigation stack.

In the first VC, I use a picker view to pick a time and then I use a button to pass "pickedTime var" and segue to the second VC. In the second VC, I successfully use the "pickedTime var" to show the picked time on the screen.

I ran into an issue after I tried to pass the "pickedTime var" again to the third VC. Although, the third screen loads, "pickedTime var" shows 0 on the screen instead of the pickedTime.

First VC code:

// Holds pickedTime from UIPickerView
var pickedTime = Int()

// Segue to second screen
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  if segue.identifier == "showSecondScreen" {
    let controller = segue.destination as! SecondViewController
    controller.pickedTime = pickedTime
  }
}

Second VC code:

// Holds pickedTime passed from first VC
var pickedTime: Int()

// Show pickedTime in label
override func viewDidLoad() {
  super.viewDidLoad()
  pickedTimeLabel.text = "\(pickedTime)"   // shows 60
}

// Segue to pop-up screen or third screen
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  if segue.identifier == "segueToPopUp" {
      let controller = segue.destination as! PopUpViewController
      ...
  } else if let controller = segue.destination as? ThirdViewController {
      controller.pickedTime = pickedTime
  }
}

Third VC code

// Holds pickedTime passed from second VC
var pickedTime: Int()

// Show pickedTime in label
override func viewDidLoad() {
  super.viewDidLoad()
  pickedTimeLabel.text = "\(pickedTime)"   // shows 0
}

Solution

  • You may not need to inject data to VC but instead share a Controller instance between and update instance. When the controller comes in the screen can checkout the values it needs and renders.

    On your Solution:

    // Holds pickedTime passed from second VC
    
    var pickedTime: Int()
    
    // Show pickedTime in label
    override func viewDidLoad() {
      super.viewDidLoad()
      pickedTimeLabel.text = "\(pickedTime)"   // shows 0
    }

    Instead of this, you can create a new Controller called Time.swift where you save the picked time and do not need to save any variable but pas entire Object as a dependency. Also keep in mind that you are creating a chain of dependencies which most often fail to because 'var pickedTime: Int()' will show 0 on first place