Pass variable returned Object via Segue depending on which button pressed

pass data between view controllers swift without segue
passing data between view controllers using delegates in swift 4
pass data between view controllers (swift with segue)
change viewcontroller on button click swift
swift pass data between classes
pass data back to previous view controller swift
prepare(for segue)
prepareforsegue swift

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

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
        }
    }
 }

Understanding the 'sender' in segues and use it to pass on data to , One of the downsides of using segues in storyboards is that you often still need to you to determine what triggered the segue in prepareForSegue:sender:, and based additional logic when pressing a button and after that perform the segue​. To do that, we need to pass on a UIColor object to the target view controller. Passing Data Using Segue. This comes to the core part of tutorial about how to pass data between view controller using Segue. Segues manages the transition between view controllers. On top of this, segue objects are used to prepare for the transition from one view controller to another.

In performSegue(withIdentifier:sender:), sender can be anything you like.

Use sender to pass the generated workout to performSegue:

//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: WorkoutGenerator.standardWorkout.generate() )

}

Then in prepare(for:sender:)

let finalWorkout = FinalWorkout(generatedWorkout: sender as! YourWorkoutGeneratorType, timeForWorkout: finalTimeForWorkout!)

Pass Data Between View Controllers (How To) – LearnAppMaking, How do you pass data between view controllers in Swift? If you then add a button to MainViewController , and connect it to the action above, the code should execute when you tap Let's find out how to pass data forward using segues. You also don't have to return the view controller you customized. Re: Passing Variables from Command Button. Thanks for the replies. rbrhodes: This looks like what I am trying to achieve. Just one question though, in the test function, you have to set the mcontrol to point to the button, is there any way of knowing in this test function which button was pressed?

If I have this right, you want to pass a different argument into your FinalWorkout() function based on which button was pressed?

It doesn't always make for very readable code, but you can use the UIButton tag property. If you set each button's tag property to a unique value [0, 1, 2], you can use that info to generate a different workout:

// This code would be in: override func prepare(for segue: UIStoryboardSegue, sender: Any?)
let buttonTag = (sender as! UIButton).tag

if buttonTag == 0 { // Generate type of workout}
else if buttonTag == 1 { // Generate type of workout }
else if buttonTag == 2 { // Generate type of workout }

Or if you're worried about tags not being an intuitive representation, you could just test for equality with the IBOutlet reference you have for each button:

let buttonPressed = sender as! UIButton

if (buttonPressed == self.yourButtonIBOutletPropertyName) { // select a workout for this button} 

I may have missed what you were asking, if this is the case comment and I'll update the answer.

Native Mobile Development: A Cross-Reference for iOS and Android, itself like an object), open up the attributes inspector, and add a unique identifier. It's common to pass a refer‐ence to a button if the segue was triggered via a This is done through the same Control-click mechanism in the storyboard editor controllers whenever a segue is performed allowing you to pass data or state to  Passing and Returning Objects in Java Although Java is strictly pass by value , the precise effect differs between whether a primitive type or a reference type is passed. When we pass a primitive type to a method, it is passed by value.

View Controller Programming Guide for iOS: Using Segues, The starting point of a segue is the button, table row, or gesture You can use the notifications sent by UIKit to pass data to the new Control-click an appropriate element in the first view controller and drag to the target view controller. The identifier is included in the UIStoryboardSegue object delivered​  partial(change_label_numer, 2) returns a callable object that behaves like a func when it is called. Pass Arguments to command in Tkinter Button with lambda function. You could also use Python lambda operator or function to create a temporary, one-time simple function to be called when Button is clicked.

Move between View Controllers with Segues, Head to the Main.storyboard and from the Object Library drag out a View Controller Head back there and click on the little button at the top of the View Controller: to the second. one to the second View Controller to close the second and return to the first. Let's send some data from the first View Controller to the second. If you want the button to only be pressed once during the whole app usage, it may be best to use one variable. Button1.OnSelect: UpdateContext({hasbeenpressed: true}) Button1.Disabled: hasbeenpressed Name the variable whatever you want.

Learning WatchKit Programming: A Hands-On Guide to Creating , awakeWithContext(context) // Configure interface objects here. Returning Data from an Interface Controller Earlier in this chapter, you saw that you can easily For example, the user may click a button in an Interface Controller and the app will Instead, you navigate using the identifier of the segue or Interface Controller. You can pass data between view controllers in 6 ways: By using an instance property (A → B) By using segues (for Storyboards) By using instance properties and functions (A ← B) By using the Delegation pattern. By using a closure or completion handler. By using NotificationCenter and the Observer pattern.

Comments
  • I take it that you know which workout the user selected when the buttons are tapped? If so, just store this workout in a property when the button is tapped and access it later when doing the segue, passing it to the target viewcontroller
  • I just had a quick skim, a bit of advice - your question has a lot of context specific detail, when you're asking about a pretty generic concept. I think you could make your question a quarter of the length and complexity.
  • thanks @Peza i will make sure I do this in future
  • this solution works - but it loads one screen with a workout on it and then loads another one straight after. The first one is the right one and the second one is wrong when I click on standard but the opposite is true when I click on 'repeaterWorkout' - do you know why might this be?
  • i had 2 segues triggering from the button my fault!