0

I have a problem about my cell's button. In my tableView each row is composed by: an image, some labels and a button. The button has a checkmark image. When it is clicked, the button's image changes. The problem is that also another button's image changes without reason. This mistake happens because my cell is reused.

I have tried to use prepareForReuse method in TableViewCell but nothing happens. I've also tried with selectedRowAt but I didn't have any results. Please help me.

Image 1:

Image 1

Image 2:

Image 2

This is my func in my custom Cell:

  override func prepareForReuse() {
    if checkStr == "uncheck"{
        self.checkBook.setImage(uncheck, for: .normal)
    } else if checkStr == "check"{
        self.checkBook.setImage(check, for: .normal)
    }
}

func isPressed(){
    let uncheck = UIImage(named:"uncheck")
    let check = UIImage(named: "check")
    if self.checkBook.currentImage == uncheck{
        checkStr == "check"
    } else self.checkBook.currentImage == check{
        checkStr == "uncheck"
    }
}

In my tableView:

  override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let selectedCell: ListPropertyUserCell = tableView.cellForRow(at: indexPath) as! ListPropertyUserCell
    let uncheck = UIImage(named:"uncheck")
    let check = UIImage(named: "check")
    if selectedCell.checkBook.imageView?.image == uncheck{
        selectedCell.checkStr = "check"
    } else if selectedCell.checkBook.imageView?.image == check{
        selectedCell.checkStr = "uncheck"
    }
}
Carlo
  • 813
  • 1
  • 15
  • 34
  • You need to track cell selection state in your table view controller, not the cell itself. You can use one of the answers here - http://stackoverflow.com/questions/28659845/swift-how-to-get-the-indexpath-row-when-a-button-in-a-cell-is-tapped/38941510#38941510 either mine or Jacob King's to get the tap event back to your table view controller – Paulw11 Oct 15 '16 at 10:41
  • 1
    @Carlo try my code your problem will be solve. – Himanshu Moradiya Oct 15 '16 at 10:44

6 Answers6

1

From the information in your post, this looks like a cell reuse issue. The problem is that the tableView reuses the cells rather than creating new ones, to maintain performance. If you haven't reset the cell's state, the reused cell will be remain configured in the old state.

For a quick fix, you can implement the prepareForReuse method on UITableViewCell.

However, you'll need to store which cell is 'checked' in your view controller if you want the checkbox to be selected after scrolling the tableView. You can store this yourself, or use the tableView's didSelectRowAtIndexPath method.

  • I think that the problem is about reusing cells but I don't know how to use this, can you edit your answer with an example? Please, I search on Internet but I don't understand well – Carlo Oct 14 '16 at 18:51
0

Try to do it like this:

var checkBook = UIImageView()

if self.checkBook.image == UIImage(named: "check"){
   self.checkBook.image = UIImage(named: "uncheck")
}
else{
   self.checkBook.image = UIImage(named: "check")
}
Jake2Finn
  • 516
  • 5
  • 19
0

UITableViewCell is reusable. You can't store state of view in cell. You should setup cell in

func tableView(UITableView, cellForRowAt: IndexPath)  

method of your data source

The easiest way to achieve that is to implement

func tableView(UITableView, didSelectRowAt: IndexPath) 
func tableView(UITableView, didDeselectRowAt: IndexPath)

methods of UITableViewDelegate

Then you can add/remove indexPath to some array in these methods and in cellForRowAtIndexPath setup cell.

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

        let cell = tableView.dequeueReusableCellWithIdentifier("YourTableViewCell") as! YourTableViewCell

        if array.contains(indexPath) {
         cell.checkBook.image = UIImage(named: "check")
        } else {
         cell.checkBook.image = UIImage(named: "uncheck")
        }

        return cell
}  
Piotr Labunski
  • 1,638
  • 4
  • 19
  • 26
0

If you're using the click on the entire cell, you can override the setSelected func in your custom cell just like that.

override func setSelected(selected: Bool, animated: Bool) {
     super.setSelected(selected, animated: animated)
     if selected {
         self.checkBook.image = UIImage(named: "check")
     } else {
         self.checkBook.image = UIImage(named: "uncheck")
    }
}
0

Try my code . here selectindex is use for get selected cell index and selectedindex is NSMutableArray that i store all selected cell value.

var selectindex : Int?
var selectedindex : NSMutableArray = NSMutableArray()
@IBOutlet var tableview: UITableView!

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

     let cell = tableView.dequeueReusableCellWithIdentifier("LikeCell", forIndexPath: indexPath)
     let like: UIButton = (cell.viewWithTag(2) as! UIButton)// like button
     let comment: UIButton = (cell.viewWithTag(3) as! UIButton) // comment button
     comment.setBackgroundImage(UIImage(named: "chat.png"), forState: UIControlState.Normal) // comment button set
     like.addTarget(self, action: #selector(self.CloseMethod(_:event:)), forControlEvents: .TouchDown)
     comment.addTarget(self, action: #selector(self.CloseMethod1(_:event:)), forControlEvents: .TouchDown)

     return cell
}


// This is my like button action method.
@IBAction func CloseMethod(sender: UIButton, event: AnyObject) {

        let touches = event.allTouches()!
        let touch = touches.first!
        let currentTouchPosition = touch.locationInView(self.tableview)
        let indexPath = self.tableview.indexPathForRowAtPoint(currentTouchPosition)!
        selectindex = indexPath.row
        if selectedindex.containsObject(selectindex!) {
             sender.setBackgroundImage(UIImage.init(named: "like (1).png"), forState: .Normal)
             selectedindex.removeObject(selectindex!)
        }else{
             sender.setBackgroundImage(UIImage.init(named: "like.png"), forState: .Normal)
             selectedindex.addObject(selectindex!)
        }

}
Himanshu Moradiya
  • 4,769
  • 4
  • 25
  • 49
0

I faced this problem recently, and did not find much about it. What solve, after much searching, was to use:

override func prepareForReuse() {

    btnAdd.setImage(nil, for: .normal) //here I use to change to none image
    super.prepareForReuse()
} 

just put this method inside your custom UITableViewCell, and set which item you want to realese stats.

Daniel Beltrami
  • 756
  • 9
  • 22