20

I'm trying to do maybe one of the simplest and more confusing things for me until now I wanna develop my own App , and in order to do it I need to be able to passing some information depending of which row user click (it's Swift lenguage)

We have a RootViewController(table view) and a DetailViewController (with 1 label and 1 image) enter image description here

(our view)

Here is the code:

@IBOutlet weak var tableView: UITableView!


var vehicleData : [String] = ["Ferrari 458" , "Lamborghini Murcielago" , "Bugatti Veyron", "Mercedes Benz Biome"]

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    var nib = UINib(nibName: "TableViewCell", bundle: nil)

    tableView.registerNib(nib, forCellReuseIdentifier: "cell")



}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return vehicleData.count
}



func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {


    let cell:TableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as TableViewCell

    cell.lblCarName.text = vehicleData[indexPath.row]

    cell.imgCar.image = UIImage(named: vehicleData[indexPath.row])

    return cell   
}

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

    performSegueWithIdentifier("DetailView", sender: self)
}

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

    if(segue.identifier == "DetailView") {

        var vc = segue.destinationViewController as DetailViewController

    }

}

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return 100
}

Custom TableViewCell class (has a xib File with cell)

class TableViewCell: UITableViewCell {


@IBOutlet weak var lblCarName: UILabel!

@IBOutlet weak var imgCar: UIImageView!

override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}

override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}

class DetailViewController: UIViewController {



    @IBOutlet weak var lblDetail: UILabel!

    @IBOutlet weak var imgDetail: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

The question is:

if user click Ferrari 458 , the lblDetail in DetailViewController would show: Ferrari 458 is a super car which is able to reach 325 km/ h ...... (whatever we want) and imgDetail would be able to show an image (whatever we want) of the car

If user click Bugatti Veyron now the lblDetail show us: Bugatti Veyron is a perfect and super sport machine. It's one of the fastest car in the world....

imgDetail show us an image of this car

Same thing with all cars depending which row we have clicked

I know the work is around prepareForSegue func in first View Controller but i was trying a lot of different ways to make it possible and anything runs ok

How we can do this???

Christian
  • 21,440
  • 9
  • 77
  • 100
FactorJose
  • 441
  • 2
  • 4
  • 14
  • I also faced the same problem when I was trying to pass a string to another view controller to store it by its name for the future. I stumbled upon this article which clearly explains it. http://www.codingexplorer.com/segue-swift-view-controllers/ – Raja Sattiraju May 04 '15 at 20:14

4 Answers4

44

Here is the example for you:

var valueToPass:String!

func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
    println("You selected cell #\(indexPath.row)!")

    // Get Cell Label
    let indexPath = tableView.indexPathForSelectedRow!
    let currentCell = tableView.cellForRowAtIndexPath(indexPath)! as UITableViewCell

    valueToPass = currentCell.textLabel.text
    performSegueWithIdentifier("yourSegueIdentifer", sender: self)
}

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

    if (segue.identifier == "yourSegueIdentifer") {
        // initialize new view controller and cast it as your view controller
        var viewController = segue.destinationViewController as AnotherViewController
        // your new view controller should have property that will store passed value
        viewController.passedValue = valueToPass
    }
}

But don't forget to create a passedValue variable into your DetailViewController.

This is just an example of passing data from one viewController to another and you can pass data with this example as you need.

And for more info refer this links.

Passing values between ViewControllers based on list selection in Swift

Use didSelectRowAtIndexPath or prepareForSegue method for UITableView?

Swift: Pass UITableViewCell label to new ViewController

https://teamtreehouse.com/forum/help-swift-segue-with-variables-is-not-working

May be this will help you.

Swift 3.0

var valueToPass:String!
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    print("You selected cell #\(indexPath.row)!")

    // Get Cell Label
    let indexPath = tableView.indexPathForSelectedRow!
    let currentCell = tableView.cellForRow(at: indexPath)! as UITableViewCell

    valueToPass = currentCell.textLabel?.text
    performSegue(withIdentifier: "yourSegueIdentifer", sender: self)
}

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){

    if (segue.identifier == "yourSegueIdentifer") {
        // initialize new view controller and cast it as your view controller
        var viewController = segue.destination as! AnotherViewController
        // your new view controller should have property that will store passed value
        viewController.passedValue = valueToPass
    }
}
Community
  • 1
  • 1
Dharmesh Kheni
  • 67,254
  • 32
  • 154
  • 160
  • Hi Dharmesh Kheni, first of all thx so much for kindness For sure all u wrote help me to understand it a little more, but still doesn't running the way I'm looking for Now the App knows what row was selected, but then I need to know how to change lblDetail and imgDetail S – FactorJose Feb 10 '15 at 14:22
  • Sorry... Somehow i think we need a if statement or something like that... but where? and how? =S I'm beginner, accept my apologies – FactorJose Feb 10 '15 at 14:24
  • just create the variable into DetailViewController which can hold the values when values are passed from segue and assign that values to that variable and after that u can show the values into DetailViewController. – Dharmesh Kheni Feb 11 '15 at 04:36
  • I have assigned the variable in DetailViewController Dharmesh , but i don't know how to tell label : ok , now show me that text if row Ferrari was clicked, or show me the other text now?? How this translated into code? thank you again – FactorJose Feb 11 '15 at 12:20
  • Remember I'm a beginner. I only need the last step but i would need to see it wrote in code – FactorJose Feb 11 '15 at 12:23
  • its navigating 2 time to the destination View – Abhishek Kumar Jul 19 '16 at 13:27
  • why `let currentCell = tableView.cellForRow(at: indexPath)! as UITableViewCell` don't works foe me? my tableView is placesTableView. I replace that in your code but still doesn't work. – Alex Andreadis May 16 '17 at 12:30
  • I am searching about 1 week but I did not found any answer. I am getting data from table view to detail view contoller without any problem. But, I do not pass this same data to another (3rd screen) table view. @dharmesh – Emre Değirmenci Mar 10 '19 at 21:14
4

This may be another solution, without much code in didSelectRowAtIndexPath method. Note that while it may look cleaner, and we do not need an extra variable valueToPass, it may not be a best practice, because the sender argument inside performSegue method is supposed to be the actual object that initiated the segue (or nil).

// MARK: UITableViewDelegate methods

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)

    performSegue(withIdentifier: "goToSecondVC", sender: indexPath)
}

// MARK: UIViewController methods

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "goToSecondVC" {    
        if segue.destination.isKind(of: CarDetailsController.self) {
            let secondVC = segue.destination as! CarDetailsController

            let indexPath = sender as! IndexPath

            secondVC.passedValue = carsArray[indexPath.row]
        }
    }
}
ppalancica
  • 4,098
  • 4
  • 25
  • 39
3

If you drag a segue from the prototype cell (in the Interface Builder) to your next View Controller and set its segue identifier to "Your Segue Identifier", you can also do it with this shortcut:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "Your Segue Identifier" {
        let cell = sender as! YourCustomCell
        let vc = segue.destination as! PushedViewController
        vc.valueToPass = cell.textLabel?.text // or custom label
    }
}

And you also don't need the performSegueWithIdentifier() in the didSelectRowAtIndexPath(), nor this Table View method.

In PushedViewController.swift (the next View Controller):

var valueToPass: String!

override func viewDidLoad() {
    super.viewDidLoad()
    yourLabel.text = valueToPass
}

It's important to set the label's value after it initialized from the Storyboard. That means, you can't set the label in the previous View Controller's prepareForSegue() directly, therefore needing to pass it with valueToPass.

Teodor Ciuraru
  • 2,949
  • 1
  • 27
  • 33
0

Its simple, am adding one statement to above answer. To get the selected car name in detail view label,

lblDetail.text = passedValue

you can add this code of line in viewDidLoad() func of your detailed view. passedValue contains the name of car which user selected(assign in prepareForSegue) then you can assign to your detailedView label.

Hope it helps!!

Pruthvi Hariharan
  • 531
  • 1
  • 5
  • 21