Tarvo Mäesepp Tarvo Mäesepp - 1 month ago 15
Swift Question

Button state activates on wrong cells

I added button into cell-s and added action so if user touches it then the state is "Dislike" and if user touches again the state is "Like". However, the state applies to other cell buttons also. And if I scroll fast it just randomly picks what cell button should have the state. What causes this?

I call button with function inside

cellForRowAt indexPath: IndexPath
function like this:

cell.likeButton.addTarget(self, action: #selector(like), for: .touchUpInside)


And this is the function that is assigned to the button:

func like(sender: UIButton){
let section = 0
let row = sender.tag
let indexPath = IndexPath(row: row, section: section)
let cell: FeedTableViewCell = tableView.dequeueReusableCell(withIdentifier: "feedCell", for: indexPath) as! FeedTableViewCell
FIRDatabase.database().reference().child("posts").child(postsArray[indexPath.row].key).runTransactionBlock({ (currentData: FIRMutableData) -> FIRTransactionResult in
if var post = currentData.value as? [String : AnyObject], let uid = FIRAuth.auth()?.currentUser?.uid {
var stars : Dictionary<String, Bool>
stars = post["stars"] as? [String : Bool] ?? [:]
var starCount = post["starCount"] as? Int ?? 0
if let _ = stars[uid] {
// Unstar the post and remove self from stars
starCount -= 1
stars.removeValue(forKey: uid)
cell.likeButton.tag = indexPath.row
cell.likeButton.setTitle("Like", for: .normal)

cell.likeLabel.text = "\(starCount)"
} else {
// Star the post and add self to stars
starCount += 1
stars[uid] = true
cell.likeButton.tag = indexPath.row
cell.likeButton.setTitle("Dislike", for: .normal)

cell.likeLabel.text = "\(starCount)"
}
post["starCount"] = starCount as AnyObject?
post["stars"] = stars as AnyObject?

// Set value and report transaction success
currentData.value = post

return FIRTransactionResult.success(withValue: currentData)
}
return FIRTransactionResult.success(withValue: currentData)
}) { (error, committed, snapshot) in
if let error = error {
print(error.localizedDescription)
}
}
}


And like this I created the tableview with cells:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: FeedTableViewCell = tableView.dequeueReusableCell(withIdentifier: "feedCell", for: indexPath) as! FeedTableViewCell

cell.likeButton.tag = indexPath.row
cell.likeButton.addTarget(self, action: #selector(self.tapped), for: .touchUpInside)
}


What causes the state to transfer to the other buttons also? I even added tags so it detects the selected button. Is there something to do with cell reuse?

It adds likes to Firebase to the right one..

Answer

I think this issue is because of dequeuing your cell twice. you should try;

func like(sender: UIButton){
    //your code ...
    let cell: FeedTableViewCell = self.tableViewAddress.cellForRowAtIndexPath(indexPath) as! FeedTableViewCell
    //Your code ...
Comments