Search code examples
iosunwind-segue

prepare for segue call before tableView didSelectRowAt indexPath iOS


I have 3 VC - VC1, VC2 & VC3

I'm creating an unwind segue where -

  1. VC1 is destination
  2. VC2 is source

So, I've add Marker function in VC1 -

@IBAction func unwindToHomeViewController(_ sender: UIStoryboardSegue) {}

and in VC2 I've created two variable -

var userSelectedPlacesLatitude: Double = 0
var userSelectedPlacesLongitude: Double = 0

which will be updated in tableView -

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    self.userSelectedPlacesLatitude = suggestedPlacenames[indexPath.row].geometry.coordinates[1]
    self.userSelectedPlacesLongitude = suggestedPlacenames[indexPath.row].geometry.coordinates[0]
    print("In didSelectRowAt", userSelectedPlacesLatitude, userSelectedPlacesLongitude)
}

and then prepare for segue -

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let destinationVC = segue.destination as! VC1
    print("In Segue preperation",userSelectedPlacesLatitude, userSelectedPlacesLongitude)
    destinationVC.userSelectedPlacesLatitude = self.userSelectedPlacesLatitude
    destinationVC.userSelectedPlacesLongitude = self.userSelectedPlacesLongitude
    destinationVC.reloadWeatherDataStatus = true
}

But from print value I'm seeing that prepareforSegue is called earlier than didSelectRowAt. Hence I'm not getting expected value in prepareforsugue

In Segue preperation 0.0 0.0
In didSelectRowAt 49.3227937844972 31.3202829593814

Hence 0.0 0.0 is passing all the time to VC1. How can I fix this problem?


Solution

  • The problem you are experiencing results from having at the unwind segue linked directly from the table view cell in your storyboard. As soon as the user taps the row, the unwind segue fires. The didSelectRow(at:) function is called after, but this is too late; You are already back in VC1.

    While you can use prepareForSegue to send data to VC1, a better approach is to use the sender passed to unwindToHomeViewController to let VC1 get the data from VC2.

    This means that VC2 doesn't need to know anything about VC1. You can also get rid of the reloadWeatherDataStatus property and simply reload the weather data status in the unwind function.

    You should:

    • Remove the segue from the table view row in VC2
    • In your storyboard, ctrl-drag from the "View controller" icon at the top of VC2 to the "Exit" icon at the top of VC2 and select unwindToHomeViewController
    • Select the newly created unwind segue and give it an identifier, say unwindToVC1
    • In VC2 you have
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        self.userSelectedPlacesLatitude = suggestedPlacenames[indexPath.row].geometry.coordinates[1]
        self.userSelectedPlacesLongitude = suggestedPlacenames[indexPath.row].geometry.coordinates[0]
        self.performSegue(withIdentifier:"unwindToVC1", sender: self)
    }
    
    • Remove prepare(for segue: sender:) from VC2

    • In VC1

    @IBAction func unwindToHomeViewController(_ sender: UIStoryboardSegue) {
        if let sourceVC = sender.source as? VC2 {
            self.userSelectedPlacesLatitude = sourceVC.userSelectedPlacesLatitude
            self.userSelectedPlacesLongitude = sourceVC.userSelectedPlacesLongitude
            // Do whatever is required to reload the data based on the new location
        }
    }