Janice Zhan
Janice Zhan

Reputation: 571

Swift two table view cell get the same value

I have used a tableview with 16 cells on a view controller. Each cell has a textfield and a picker view as a inputview for textfield. The odd thing is that When I choose the value for the first cell, it's fine. When I scrolled down to the last cell, the value is same as the first one. But I have never touched the last cell. Why would this happened?

func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
    // selected value in Uipickerview in Swift
    answerText.text = pickerDataSource[row]
    answerText.tag = row
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    let cell = myTable.dequeueReusableCellWithIdentifier("addFollowCell", forIndexPath: indexPath) as! AddFollowTableViewCell
    cell.questionView.text = listQuestion1[indexPath.row]
    cell.pickerDataSource = dictPicker[indexPath.row]!
    cell.answerText.addTarget(self, action: #selector(AddFollowUpViewController.textFieldDidChange(_:)), forControlEvents: UIControlEvents.EditingDidEnd)
    return cell
}

func textFieldDidChange(sender: UITextField){
    let rowIndex: Int!
    let selectValue = sender.tag

    if let txtf = sender as? UITextField {
        if let superview = txtf.superview {
            if let cell = superview.superview as? AddFollowTableViewCell {
                rowIndex = myTable.indexPathForCell(cell)?.row
                dictAnswer[rowIndex] = selectValue - 1
            }
        }
    }
}

After two days, it solved by thousands of trials:

     func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    var cell = myTable.dequeueReusableCellWithIdentifier("addFollowCell") as! AddFollowTableViewCell
    if(cell.identifier == true){
        cell.answerText.text = selectedAnswerForRow[indexPath.row]
    }
    cell.questionView.text = listQuestion1[indexPath.row]
    cell.pickerDataSource = dictPicker[indexPath.row]!
    dictAnswer[indexPath.row] = cell.pickerValue
    cell.answerText.addTarget(self, action: #selector(AddFollowUpViewController.textFieldDidChange(_:)), forControlEvents: UIControlEvents.EditingDidEnd)
    cell.identifier = true

  return cell
}

func textFieldDidChange(sender: UITextField){
    let rowIndex: Int!
    let cell = sender.superview?.superview as! AddFollowTableViewCell
    rowIndex = myTable.indexPathForCell(cell)?.row
    selectedAnswerForRow[rowIndex] = cell.answerValue
    print(selectedAnswerForRow[rowIndex])
    cell.answerText.text = sender.text
    cell.identifier = true

}

It might have some performance issue need to be optimised , but it shows exactly what i want. LOL

Upvotes: 0

Views: 858

Answers (2)

CZ54
CZ54

Reputation: 5586

Because the cell is reused. So you have to implement prepareForReuse() in your custom cell class and reset all the changing variables

UPDATE

See :

class MyCell : UITableViewCell {

    @IBOutlet weak var myTextField : UITextField!

    //Add the following
    override func prepareForReuse() {
    myTextField.text = nil
    myTextField.inputView = myPickerView
    super.prepareForReuse()
   }
}

Upvotes: 0

Crazyrems
Crazyrems

Reputation: 2591

You're basically recycling your views and not clearing them. That's the whole point of -dequeueReusableCellWithIdentifier:indexPath:.

Allocating and deallocating memory is very power consuming, so the system recycles every cell that goes out of viewport bounds.

You don't set the text inside answerText (I assume it's the text field that causes trouble) so its content will be kept when recycled.

Assuming you'll store user selection inside a dictionary var selectedAnswerForRow: [IndexPath:String]:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    let cell = myTable.dequeueReusableCellWithIdentifier("addFollowCell", forIndexPath: indexPath) as! AddFollowTableViewCell
    cell.questionView.text = listQuestion1[indexPath.row]
    cell.pickerDataSource = dictPicker[indexPath.row]!
    cell.answerText.addTarget(self, action: "textFieldDidChange:"), forControlEvents: UIControlEvents.EditingDidEnd)
    cell.answerText.text = self.selectedAnswerForRow[indexPath] ?? "" // add this
    return cell
}

self.selectedAnswerForRow[indexPath] ?? "" returns the result or an empty string if it's not present in the dictionary.


Also, you're adding several times the action for edition control event. You have to check first if it isn't already bound.

Upvotes: 2

Related Questions