Sending Variables with a Segue

How to Pass Variables and Objects from a Subclass via a Segue in Swift 3.0

  1. Another option is to call

    "func performSegue(withIdentifier identifier: String, sender: Any?)"

    which will trigger a segue from ViewController to
    SecondViewController. This is you like to keep the code of moving between ViewControllers in the storyboard ie, you controlled dragged from ViewController to SecondViewController to create a segue and gave it a unique id.

  2. Every UIViewController (subclass of) inherits a function

    "func prepare(for segue: UIStoryboardSegue, sender: Any?)"

    which will be called by the system, this is where you can add
    implementation to as the name suggest prepare anything needed before
    a particular segue is performed. At this time the next
    ViewController have been loaded from the Storyboard into memory (but
    have not begin to be displayed). And the "segue"* parameter of
    "prepare(for segue: UIStoryboardSegue, sender: Any?)" actually has a
    property "destination" which is actually the next ViewController.

    Be Careful though, as you may have more than 1 segue from this
    ViewController to different next ViewController.

    So "segue.destination" may not be your desired SecondViewController if
    you have more than 1 segue setup. Because the system calls
    "prepare(for segue: UIStoryboardSegue, sender: Any?)" for every
    segue leaving this current ViewController. Make sure you check
    "segue.identifier" to make sure your subsequent code are dealing
    with the same segue you think you are.

  3. Now you are finally able to do what your headline question is about.
    with a pointer to the SecondViewController you are free to set any
    property it has, which is the particular instance of your Capital
    object. To come full circle, the "sender" parameter of
    "performSegue(withIdentifier identifier: String, sender: Any?)"* and
    "prepare(for segue: UIStoryboardSegue, sender: Any?)" are actually the
    samething. So you can actually pass any object/struct you like from
    "performSegue()" to "prepare(for:)" Simply cast the sender object into the
    type you passed after confirming the "segue.identifier."


func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
let capital = view.annotation as! Capital
let placeName = capital.title
let placeInfo = capital.info

// Option 1
perform segue.performSegue(withIdentifier: "SegueToSecondID", sender: capital)

//Option 2 programmatically create SecondViewController and show.
let SecondViewController = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController")
SecondViewController.capital = capital
self.show(SecondViewController!, sender: nil)
}

// If you are doing option 1
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "SegueToSecondID" && sender is Capital {
let destination = segue.destination as SeconViewController
destination.capital = sender
}
}

class SecondViewController {
//........
var capital: Capital? //Up to you if you want this as an optional

}

Pass data through segue

Swift works exactly the same way as Obj-C but is reworked in the new language. I don't have a lot of information from your post but let's give a name to each TableViewController to help with my explanation.

HomeTableViewController (this is the screenshot you have above)

PlayerTableViewController (this is the player screen you want to travel to)

With that said, in PlayerTableViewController you need to have a variable that will store the passed data. Just under your class declaration have something like this (if you intend to store the struct as a single object rather than the array:

class PlayerTableViewController: UITableViewController {

var programVar : Program?

//the rest of the class methods....

After that there are two ways you can send data to the new TableViewController.

1) Using prepareForSegue

At the bottom of HomeTableViewController you will use the prepareForSegue methods to pass the data. Here is an example of the code you'll use:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {

// Create a variable that you want to send
var newProgramVar = Program(category: "Some", name: "Text")

// Create a new variable to store the instance of PlayerTableViewController
let destinationVC = segue.destinationViewController as PlayerTableViewController
destinationVC.programVar = newProgramVar
}
}

Once PlayerTableViewController has loaded the variable will be already set and usable

2) Using didSelectRowAtIndexPath

If specific data needs to be sent based on which cell is selected you can use didSelectRowAtIndexPath. For this to work, you need to give your segue a name in the storyboard view (let me know if you need to know how to do this too).

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

// Create a variable that you want to send based on the destination view controller
// You can get a reference to the data by using indexPath shown below
let selectedProgram = programy[indexPath.row]

// Create an instance of PlayerTableViewController and pass the variable
let destinationVC = PlayerTableViewController()
destinationVC.programVar = selectedProgram

// Let's assume that the segue name is called playerSegue
// This will perform the segue and pre-load the variable for you to use
destinationVC.performSegueWithIdentifier("playerSegue", sender: self)
}

Let me know if you need any other info on this

How to send multiple variables through segue

As in Tiago's answer, you can create a new struct or class which has QBName and QBBust properties. In addition, you can also use tuple in Swift.

This is an example:

in Destination ViewController

declare var QBInfo:(name: String, bust: Double)?

and in the button function that triggers the segue

let QBInfo = (name: QBName, bust: QBBust)
performSegue(withIdentifier: "QBResultVC", sender: QBBust)

then in prepareForSegue:sender:method

destination.QBInfo = QBInfo

Pass variable returned Object via Segue depending on which button pressed

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

Pass multiple variables through segue in Swift

You need to use the prepare function:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "player" {
if let player = sender as? Player {
let secondViewController = segue.destination as! SecondViewController
secondViewController.player = player
}
}
}

This function will be called when you call performSegue. Declare a player variable in your secondViewController and you´ll just pass the variable in your prepare function.

And in your didSelectRowAt change:

let selectedPlayer = player[indexPath.row].playerName

To:

let selectedPlayer = player[indexPath.row]

So you pass the entire Player object instead of just the playerName.

how to pass variables between view controllers without a segue in swift

I can't do this through segues because the sequence of view controllers looks like this: 1 -> 2 -> 3 -> 4 -> 5 and I need to get data from 1 to 5

To say "can't" is just silly. Of course you can. You just keep passing and accumulating the information so that everything needed gets to 5. You just mean you don't want to, either because you think it's ugly or because you don't want to take the time to implement it.

But why not? Why not pass, say, a single custom object with all the needed properties that gets populated more and more, and is modified as needed, as it moves down the line until it reaches 5?



Related Topics



Leave a reply



Submit