Reputation: 154
I have a Button in a custom cell which changes image after being pressed, but whenever a reload is triggered the newly added cell has the changed image instead of the old one. This is my cellForRowAt:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Sender", for: indexPath) as! Sender
cell.clearCellData()
cell.message.text = self.items[indexPath.row].content
cell.name.text = self.items[indexPath.row].name
cell.from = self.items[indexPath.row].fromID
return cell
}
The button's outlet and actions are both in Button cell like this:
@IBAction func downVoted(_ sender: Any) {
if(self.downVote.image(for: .normal) == #imageLiteral(resourceName: "DownGray")){
self.downVote.setImage(#imageLiteral(resourceName: "DownOn"), for: .normal)
}else{
self.downVote.setImage(#imageLiteral(resourceName: "DownGray"), for: .normal)
}
}
It works fine until a new row is added. I have tried setting the buttons tags the same as the cell tags but it didn't help. Does anyone know a fix for this?
Thank you.
Upvotes: 0
Views: 153
Reputation: 566
This may be because of cells are reused, try to set images in cellForRowAt:
to do so you need to have a bool(selected or not) in your model, you have to use delegate for touch , and implement it in your controller, so you can change your model at index and reload table view, I provide sample code
protocol SenderDelegate {
func downVoteTapped(_ cell: MainTVCell)
}
class Sender: UITableViewCell {
@IBAction func downVoted(_ sender: Any) {
delegate!.downVoteTapped(self)
}
}
and controller
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Sender", for: indexPath) as! Sender
cell.clearCellData()
cell.delegate = self
cell.message.text = self.items[indexPath.row].content
cell.name.text = self.items[indexPath.row].name
cell.from = self.items[indexPath.row].fromID
if self.items[indexPath.row].selected == true {
self.downVote.setImage(#imageLiteral(resourceName: "DownOn"), for: .normal)
} else {
self.downVote.setImage(#imageLiteral(resourceName: "DownGray"), for: .normal)
}
return cell
}
func downVoteTapped(_ cell: Sender) {
let index = tableView.indexPathForCell(cell)?.row)!
self.items[index].selected == !self.items[index].selected
tableView.reloadData()
}
and don't forget to do SomeViewController: SenderDelegate
and in your model var selected = false
Upvotes: 1
Reputation: 864
This is because you need to setup the state of the button in
cellForRowAt indexPath:
delegate method each time it's called.
Therefore you should store the state of the button somewhere, it can be an array or plist.
You have your items stored in the array and I can suggest to add a property to it var isLiked: Bool
, and you should change that property once the button was pressed, and accords to that property you should either set selected or unselected image in your cellForRowAt indexPath:
method
Upvotes: 0