Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: Pass UITableViewCell label to new ViewController

I have a UITableView that populates Cells with data based on a JSON call. like so:

var items = ["Loading..."]
var indexValue = 0

// Here is SwiftyJSON code //

for (index, item) in enumerate(json) {
    var indvItem = json[index]["Brand"]["Name"].stringValue
    self.items.insert(indvItem, atIndex: indexValue)
    indexValue++
}
self.tableView.reloadData()

How do I get the label of the cell when it is selected and then also pass that to another ViewController?

I have managed to get:

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!;

    println(currentCell.textLabel.text)
}

I just cant figure out how to pass that as a variable to the next UIViewController.

Thanks

like image 406
MarkP Avatar asked Feb 04 '15 06:02

MarkP


3 Answers

Passing data between two view controllers depends on how view controllers are linked to each other. If they are linked with segue you will need to use performSegueWithIdentifier method and override prepareForSegue method

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
    }

}

If your view controller are not linked with segue then you can pass values directly from your tableView function

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!;
    let storyboard = UIStoryboard(name: "YourStoryBoardFileName", bundle: nil)
    var viewController = storyboard.instantiateViewControllerWithIdentifier("viewControllerIdentifer") as AnotherViewController
    viewController.passedValue = currentCell.textLabel.text
    self.presentViewController(viewContoller, animated: true , completion: nil) 
}
like image 97
Zell B. Avatar answered Oct 17 '22 00:10

Zell B.


You asked:

How do I get the label of the cell when it is selected and then also pass that to another ViewController?

I might suggest rephrasing the question as follows: "How do I retrieve the data associated with the selected cell and pass it along to another view controller?"

That might sound like the same thing, but there's an important conceptual distinction here. You really don't want to retrieve the value from the cell label. Our apps employ a MVC paradigm, so when you want to pass data information from one scene to another, you want to go back to the model (the items array), not the view (the text property of the UILabel).

This is a trivial example, so this distinction is a bit academic, but as apps get more complicated, this pattern of going back to the model becomes increasingly important. The string representation from the cell is generally is a poor substitute for the actual model objects. And, as you'll see below, it's just as easy (if not easier) to retrieve the data from the model, so you should just do that.

As an aside, you don't really need a didSelectRowAtIndexPath method at all in this case. All you need is a segue from the table view cell to the destination scene, give that segue a unique identifier (Details in my example), and then implement prepare(for:sender:):

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destination = segue.destination as? DetailsViewController {
        let selectedRow = tableView.indexPathForSelectedRow!.row
        destination.selectedValue = items[selectedRow]
    }
}

Alternatively, if your segue is between the cell and destination scene, you can also use the sender of the prepare(for:sender:):

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destination = segue.destination as? DetailsViewController {
        let cell = sender as! UITableViewCell
        let selectedRow = tableView.indexPath(for: cell)!.row
        destination.selectedValue = items[selectedRow]
    }
}

But the idea is the same. Identify what row was selected, and retrieve the information from the model, the items array.

The above is Swift 3. For Swift 2.3, please see the previous version of this answer.

like image 29
Rob Avatar answered Oct 17 '22 00:10

Rob


Okay..Its been 2 days I was searching for the answer that how could I be able to save the selected UITableViewCell label text data and display that data to an another label on an another View Controller which will come out after tapping on a cell. At last I have completed with the task and its successful. Here is the complete code with steps using Swift.I am using Xcode 6.4.

Step 1.

I have Two class assigned to the storyboard view controllers named "iOSTableViewControllerClass.swift" which is a Table View Controller and "iOSTutorialsViewControllerClass.swift" which is a normal View Controller.

Step 2.

Now make segue from iOSTableViewControllerClass to iOSTutorialsViewControllerClass by Control-dragging on the storyboard area and choose "show" from drop down menu. Click on this highlighted button according to the below image and perform the segue.

Make Segue by selecting this icon an control-drag to the other view Controller

Step 3.

Now select the segue by clicking on the storyboard and give it an identifier on the Attributes Inspector. In this case I named it as "iOSTutorials"

Select Segue on the storyboard and name it

Step 4.

Now on this step put a label on your cell as well as on the other view controller and make outlets of them on their corresponding classes. In my case those are "@IBOutlet weak var iOSCellLbl: UILabel!" and " @IBOutlet weak var iOSTutsClassLbl: UILabel!".

Step 5.

Make a string type variable on the first Table View Controller Class. I did this as "var sendSelectedData = NSString()" also Make a string type variable on the second class. I did this as "var SecondArray:String!".

Step 6.

Now we are ready to go. Here is the complete Code for first Class --

 // iOSTableViewControllerClass.swift

  import UIKit

  class iOSTableViewControllerClass: UITableViewController, UITableViewDataSource,UITableViewDelegate {

  // Creating A variable to save the text from the selected label and send it to the next view controller

  var sendSelectedData = NSString()

 //This is the outlet of the label but in my case I am using a fully customized cell so it is actually declared on a different class
@IBOutlet weak var iOSCellLbl: UILabel!

//Array for data to display on the Table View
var iOSTableData = ["Label", "Button", "Text Field", "Slider", "Switch"];
override func viewDidLoad() {
    super.viewDidLoad()

//Setting the delegate and datasource of the table view

    tableView.delegate = self
    tableView.dataSource = self

//Registering the class here
    tableView.registerClass(CustomTableViewCellClassiOS.self, forCellReuseIdentifier: "CellIDiOS")

//If your using a custom designed Cell then use this commented line to register the nib.
    //tableView.registerNib(UINib(nibName: "CellForiOS", bundle: nil), forCellReuseIdentifier: "CellIDiOS")
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // Return the number of sections.
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // Return the number of rows in the section.
    return iOSTableData.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let CellIDentifier = "CellIDiOS"

 //In this case I have custom designed cells so here "CustomTableViewCellClassiOS" is the class name of the cell
    var cell:CustomTableViewCellClassiOS! = tableView.dequeueReusableCellWithIdentifier(CellIDentifier, forIndexPath: indexPath) as? CustomTableViewCellClassiOS
    if cell == nil{
        tableView.registerNib(UINib(nibName: "CellForiOS", bundle: nil), forCellReuseIdentifier: CellIDentifier)
        cell = tableView.dequeueReusableCellWithIdentifier(CellIDentifier) as? CustomTableViewCellClassiOS

    }
 //Here we are displaying the data to the cell label
    cell.iOSCellLbl?.text = iOSTableData[indexPath.row]
    return cell
}

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

    println("You selected cell #\(indexPath.row)!")

    // Get Cell Label text here and storing it to the variable
    let indexPathVal: NSIndexPath = tableView.indexPathForSelectedRow()!
    println("\(indexPathVal)")
    let currentCell = tableView.cellForRowAtIndexPath(indexPathVal) as! CustomTableViewCellClassiOS!;
    println("\(currentCell)")
    println("\(currentCell.iOSCellLbl?.text!)")
    //Storing the data to a string from the selected cell
    sendSelectedData = currentCell.iOSCellLbl.text!
    println(sendSelectedData)
//Now here I am performing the segue action after cell selection to the other view controller by using the segue Identifier Name
    self.performSegueWithIdentifier("iOSTutorials", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

//Here i am checking the Segue and Saving the data to an array on the next view Controller also sending it to the next view COntroller
    if segue.identifier == "iOSTutorials"{
//Creating an object of the second View controller
        let controller = segue.destinationViewController as! iOSTutorialsViewControllerClass
//Sending the data here
        controller.SecondArray = sendSelectedData as! String

 }

Here is the complete code for the second Class..--

//  iOSTutorialsViewControllerClass.swift

import UIKit

class iOSTutorialsViewControllerClass: UIViewController {

//Creating the Outlet for the Second Label on the Second View Controller Class
@IBOutlet weak var iOSTutsClassLbl: UILabel!

//Creating an array which will get the value from the first Table View Controller Class
var SecondArray:String!

override func viewDidLoad() {
    super.viewDidLoad()

//Simply giving the value of the array to the newly created label's text on the second view controller
   iOSTutsClassLbl.text = SecondArray
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}
like image 4
onCompletion Avatar answered Oct 17 '22 00:10

onCompletion