0

While there are many questions and answers to this subject, none of them fully explain what has to be done. Similar to the Reddit upvote feature or Instagrams post, I'm trying to click a button inside a collection view cell and have it's button changed when such happens.

When I do click, other cells are affected.

Here is my code:

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cartBookView", for: indexPath) as! CartBookPreviewCell

 cell.saveButton.tag = indexPath.row

 cell.saveButton.addTarget(self, action: #selector(self.clickLike(sender:)), for: .touchUpInside)

        return cell
}

func clickLike(sender: UIButton) {
    let index: Int = sender.tag
    if lib.Library[index].saved {
        sender.setImage(#imageLiteral(resourceName: "Vector"), for: .normal)
        lib.Library[sender.tag].saveBook(save: false)
    }
    else {
        sender.setImage(#imageLiteral(resourceName: "Vector-Saved"), for: .normal)
        lib.Library[sender.tag].saveBook(save: true)
    }
    print(index)
    print(sender.tag)
}


//"Lib" is an object of a Book Collection Class that Holds an array Books. One of the attributes of the Book Class is a Boolean called save.

What am I doing wrong that makes causes other cell's button to change images despite saving the buttons' tag as indexPath

Jevon Cowell
  • 411
  • 1
  • 3
  • 13
  • 1
    Cells are reused as the table scrolls, so in your `cellForRowAt` function you need to set the image based on the current selected state of the cell – Paulw11 Feb 19 '17 at 21:57
  • @Paulw11 Am I not doing that that by assigning that tags from indexPath.row and then using that tag to change the selected button? – Jevon Cowell Feb 19 '17 at 22:03
  • 2
    You are doing it when the button is tapped, but not when the cell is retrieved via `dequeueReusableCell`. This may give you a cell that has been used previously for a different index path , so you need to set the image correctly. Also, with this approach you are constantly adding button action methods. I would suggest that you handle the button tap in the cell class and use a delegate method to inform the collection view controller. Also the use of tags is fragile since this will break if cells are reordered – Paulw11 Feb 19 '17 at 22:06
  • @Paulw11 Would you mind showing some pseudo-example code? I'm not fully understanding here. – Jevon Cowell Feb 19 '17 at 22:16
  • 1
    You can see my answer here http://stackoverflow.com/questions/28659845/swift-how-to-get-the-indexpath-row-when-a-button-in-a-cell-is-tapped/38941510#38941510 for a suggestion as to how to handle the tap in the cell; that answer is for table views, but collection views are essentially the same. – Paulw11 Feb 19 '17 at 22:18
  • @Paulw11 I like your use of Protocol (especially how I don't have to rely on tags now) though I'm kinda struggling on getting just the current cell's button. As i see it, if were to use indexPath.row, it will eventually affect the cells that will be reused. – Jevon Cowell Feb 19 '17 at 22:47
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/136106/discussion-between-jevon-coo-and-paulw11). – Jevon Cowell Feb 19 '17 at 22:49

0 Answers0