Search code examples
iosswiftsegueswift4uistoryboardsegue

Pass variable returned Object via Segue depending on which button pressed


I have a WorkoutGenerator struct which returns different workouts based on different parameters, for example generateWorkout.standardWorkout returns something different to generateWorkout.hardWorkout.

I have 3 buttons on a 'Workout Setup' page, each meant to pass a different type of workout to the 'Workout Page' (there is also an input field for 'workout time').

I have currently have one segue goToWorkout from "Workout Setup Page" to "Workout Page"

What I want to do, is trigger the segue to the workout page, passing the different workouts depending on what the user presses.

So far I have :

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    //currently have one segue between the pages
    if segue.identifier == "goToWorkout" {

        let finalTimeForWorkout = Int(timeInputField.text!)              
        //set a standardWorkout to pass to Workout Page
        let finalWorkout = FinalWorkout(generatedWorkout: WorkoutGenerator.standardWorkout.generate(), timeForWorkout: finalTimeForWorkout!)

        //set the final parameters ready to pass
        let finalWorkoutTime = finalWorkout.timeForWorkout
        let finalWorkoutExercises = finalWorkout.generatedWorkout.workoutExercises

        if let destVC = segue.destination as? WorkoutController {
            destVC.selectedWorkoutExerciseArray = finalWorkoutExercises
            destVC.selectedWorkoutTime = finalWorkoutTime

        }
    }
}  

and then something like this for each button :

//use this button to pass a standard workout
//want to pass a diff workout if a diff button pressed
@IBAction func standardWorkoutPressed(_ sender: UIButton) {
    performSegue(withIdentifier: "goToWorkout", sender: self )
}

My problem after playing around with it for a few hours is how to elegantly pass a different workout to the workout page.

i.e. I guess I could literally just copy and paste all the code for each button and make a new segue for each but that seems like the wrong way to do it!

The sort of thing I've tried is defining the workouts as variables in an if else if section but then the final workouts are out of scope for the segue.

Hope this makes sense, answers I can find about conditional segues seem to mostly refer to 'only allow the segue to happen under this condition' rather than pass different data sets to the same destination. e.g. example1 and example2


Solution

  • I'll add my comment as an answer instead, to make it easier to show some code examples.

    Add a property to your viewcontroller:

    var selectedWorkout : FinalWorkout!
    

    in each of your three button action methods you set this property to the workout associated with each button. So for your standard workout:

    @IBAction func standardWorkoutPressed(_ sender: UIButton) {
        let finalTimeForWorkout = Int(timeInputField.text!)
    
        self.selectedWorkout = FinalWorkout(generatedWorkout: WorkoutGenerator.standardWorkout.generate(), timeForWorkout: finalTimeForWorkout!)
        performSegue(withIdentifier: "goToWorkout", sender: self )
    }
    

    Finally:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "goToWorkout" {
            let finalWorkoutTime = selectedWorkout.timeForWorkout
            let finalWorkoutExercises = selectedWorkout.generatedWorkout.workoutExercises
            if let destVC = segue.destination as? WorkoutController {
                destVC.selectedWorkoutExerciseArray = finalWorkoutExercises
                destVC.selectedWorkoutTime = finalWorkoutTime
            }
        }
     }