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
passing tapped cell data to another view via segue in Swift
Make sure that you have created your segue from the view controller object in the storyboard and not the cell; if you create the segue from the cell, then the segue will fire before didSelectRowAt
is called.
Once you have set the segue correctly, you can use the sender
parameter to avoid the use of the detailToSend
property:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var detailToSend: SingleRepository
if filteredResult.count > 0 {
detailToSend = filteredResult[indexPath.row]
} else {
detailToSend = finalArrayUnwrapped[indexPath.row]
}
performSegue(withIdentifier: "showDetailSegue", sender: detailToSend)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? DetailViewController, let detailToSend = sender as? SingleRepository {
vc.detail = detailToSend
}
}
Passing data to new ViewController through Segue
You define
var films: [Results]
and then call
performSegue(withIdentifier: "detailsSegue", sender: films)
and then cast
let filmCell = sender as? Results
which will not work since Results
is not [Results]
, decide if you want an array of Result
s or just one.
passing data via segue using didSelectRowAt
Your prepare for segue
should not be in inside override func tableView(
move it so its like this:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
rowselected = indexPath.row
self.performSegue(withIdentifier: "dayx", sender: self)
}
also should be override:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "dayx" {
let destinationVC = segue.destination as! foodinfo
destinationVC.counter = rowselected
}
}
because override func prepareForSegue
method is called after self.performSegue
. So now you can successfully set the value rowSelected = indexPath.row
inside override func tableView(
and when self.performSegue
is called it will correctly pass the data as set in the override func prepareForSegue
How can I pass data between views via segue in a Xamarin.mac Cocoa app?
First, you need to set a public property in your second view controller :
public Person MainPerson { get; set; }
You’ll need to override the method called PrepareForSegue
. Inside it, you identify the destination controller (your second view), and in case you have multiple segues, it is a good practice to use a switch case statement.
public override void PrepareForSegue(NSStoryboardSegue segue, NSObject sender)
{
base.PrepareForSegue(segue, sender);
switch (segue.Identifier)
{
case "LaunchSecondView":
{
SecondViewClass target = segue.DestinationController as SecondViewClass;
target.Person = CurrentPerson;
}
break;
}
}
Passing data with segue from UITableView to UIViewController
From what I suspect, you have not programmatically pushed your segue.
Taking hint from here, did you push the segue from your didSelectRowAtIndexPath method?
Prepare for segue function can't pass data to another VC Swift,
First of all rather than declaring an extra property or saving the value to UserDefaults
you can pass the string in the sender
parameter
let action = UIAlertAction(title: "Download", style: .default) { (action) in
guard let textField = alert.textFields?.first else {return}
self.performSegue(withIdentifier: "segAdd", sender: textField.text!)
}
Your way to determine the destination view controller is wrong. Ask the segue
for the destination
. And you can force downcast the type. The code must not crash if the segue is designed correctly.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segAdd" {
let destinationVC = segue.destination as! BrowserWebViewController
destinationVC.urlFromDownloads = sender as! String
print("The value of destinationVC?.urlFromDownloads is \(destinationVC.urlFromDownloads)")
}
}
Pass data with segue Model View Presenter
You asked:
Is correct to calling vc presenter (like in first class when I call
homeDetailVC.presenter.convertData(homeData: home[selectedIndex]))
during segue?
I would generally avoid having a view controller reach in and call some method of some property (i.e., the presenter) of another view controller. You are tightly coupling/entangling each source view controller with implementation details of its destination view controller(s). E.g., you are requiring that the home view controller knows that the details view controller has a presenter, and that this presenter has a convertData
method, etc.
That is not good. You want to keep all of these various classes as loosely coupled as possible. All you care about is whether the destination view controller can receive some data.
Here is one example implementation. E.g., I might suggest a protocol to indicate whether the destination can receive some particular model object(s), e.g.,
protocol WorkoutDetailsReceiver { // is some destination capable of receiving `Workout` information
func receive(_ value: Workout)
}
Then the presenter for the destination view controller would conform to this, updating its model with the supplied value:
extension HomeDetailsPresenter: WorkoutDetailsReceiver {
func receive(_ value: Workout) {
workout = value // e.g. save the data that was passed to this presenter
// And if you want to do some conversion/processing of the data, do that here,
// but the caller should not be involved in those sorts of details.
}
}
But rather than having the source view controller from reaching into the destination view controller and invoke some method in its presenter, I personally use the same protocol, with a simple implementation that passes it along to its presenter:
extension HomeDetailsVC: WorkoutDetailsReceiver {
func receive(_ value: Workout) {
presenter.receive(value)
}
}
Having set up this pattern for receiving data, now the home view controller only needs to see if the destination can receive the Workout
information:
class HomeViewController: UIViewController {
lazy var presenter = HomePresenter(delegate: self)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let receiver = segue.destination as? WorkoutDetailsReceiver {
presenter.supplyWorkout(to: receiver)
}
}
}
Note, because we have a MVP app, the HomeViewController
does not hold any model data. Its own presenter has that. So we have some method for the source view controller to pass along the necessary data to the destination.
E.g.,
class HomePresenter {
private weak var delegate: HomePresenterDelegate?
private var workouts: [Workout] = []
private var selectedIndex: Int?
init(delegate: HomePresenterDelegate) {
self.delegate = delegate
}
// just as an example
func supplyWorkout(to receiver: WorkoutDetailsReceiver) {
guard let selectedIndex = selectedIndex else {
return
}
receiver.receive(workouts[selectedIndex])
}
...
}
Anyway, the end result is that the home view controller only needs to know whether the destination (the details view controller) can receive the information that you want to pass.
- Using MVP pattern is correct to take values directly from presenter when prepare segue (like in
homeDetailsVC
in preparing seguedestinationVC.workoutNameText = presenter.titleValue
)? Or maybe better approach is create variables directly in view controller and update them from presenter with delegates?
I once tried this “individual properties” approach: It works, but I found it to be brittle. As the app evolves, you want to change what data the destination wants, and if you have individual variables, it is too easy to forget about some property that needs to be passed along. Also, as you start injecting lots of properties from one scene to another, you end up littering the view controller with a lot of those staging properties (whether stored or computed) that really belong in its presenter. By having a protocol, you have a simple, consistent contract between the source and destination about what data the destination expects.
Now, all of that having been said, do not get too lost in the above details. There are lots of variations on the theme. But the governing principle is that we should keep our objects loosely coupled.
Related Topics
Swift Compiler Error: "Expression Too Complex" on a String Concatenation
Iphone Uitextfield - Change Placeholder Text Color
Uiscrollview Horizontal Paging Like Mobile Safari Tabs
Preferredstatusbarstyle Isn't Called
Play Youtube Videos With Mpmovieplayercontroller Instead of Uiwebview
How to Create a Multiline Uitextfield
How to Insert New Cell into Uitableview in Swift
How to Pass Textfield Value to View Controller Through Button Click in Swift Ui
Image Resolution For New Iphone 6 and 6+, @3X Support Added
Get User'S Current Location/Coordinates
How to Convert Uiview to Pdf Within Ios
Ios 7 - Status Bar Overlaps the View
Rotate Scncamera Node Looking At an Object Around an Imaginary Sphere