Search code examples
iosswiftvariablesnullsegue

Variable returns nil value after changing its value from another swift file


I'm trying to change a value of a variable from another Swift file, but for some reason it does not work and it returns nil.

This is what I have tried:

class ShowIssues: UIViewController, UITableViewDataSource, UITableViewDelegate {
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let si = self.storyboard?instantiateViewController(withIdentifier: "ShowIssueDetail") as! ShowIssueDetail
    si.idSelected = indexPath.row //Here I change the value of the variable
    performSegue(withIdentifier: "ShowIssueDetail", sender: self)
  }
}

ShowIssueDetail.swift:

class ShowIssueDetail: UITableViewController {
  var idSelected: Int! //This is the variable I want to change its value from the another swift file
    override func viewDidLoad() {
      print(idSelected) //Here it prints out nil instead of the selected row
    }
}

I have also tried it in this way, but same issue:

class ShowIssues: UIViewController, UITableViewDataSource, UITableViewDelegate {
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let si = ShowIssueDetail()
    si.idSelected = indexPath.row //Here I change the value of the variable
    performSegue(withIdentifier: "ShowIssueDetail", sender: self)
  }
}

What am I doing wrong?

Thank you in advance!

Note: Both swift files are of different type, ShowIssues.swift is UIViewController and ShowIssueDetail is UITableViewController, I do not know if it does not work due to this.


Solution

  • Your approach is wrong here:

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let si = self.storyboard?instantiateViewController(withIdentifier: "ShowIssueDetail") as! ShowIssueDetail
        si.idSelected = indexPath.row //Here I change the value of the variable
        performSegue(withIdentifier: "ShowIssueDetail", sender: self)
    }
    

    You are creating another instance of the VC and setting the value. That VC is not the actual one that will be shown.

    You need to use the prepareForSegue method

    var selectedRow: someTypeSameAsRow?
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        selectedRow = indexPath.row
        performSegue(withIdentifier: "ShowIssueDetail", sender: self)
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "ShowIssueDetail",
            let vc = segue.destination as? ShowIssueDetail {
            vc.idSelected = selectedRow
        }
    }
    

    EDIT:

    What you may need to do to resolve the error mentioned in the comments is wait until the detail view is loaded properly. The awakeFromNib function should work here:

    // this goes in the view controller
    override func awakeFromNib() {
        super.awakeFromNib()
    
        self.detailView.selected = selected
    }
    

    So, with this code you are waiting until the view of the VC and it's subviews are fully loaded and then setting the selected property of showDetailView to the same selected property that is on the VC.