Button state activates on wrong cells

风格不统一 提交于 2019-12-19 11:29:28

问题


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..


回答1:


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 ...



回答2:


 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)
        let comment: UIButton = (cell.viewWithTag(3) as! UIButton)
        if selectedindex.containsObject(indexPath.row) {
                like.setBackgroundImage(UIImage.init(named: "like.png"), forState: .Normal)
        }else{
                like.setBackgroundImage(UIImage.init(named: "like (1).png"), forState: .Normal)
        }
       comment.setBackgroundImage(UIImage(named: "chat.png"), forState: UIControlState.Normal)
        like.addTarget(self, action: #selector(self.CloseMethod(_:event:)), forControlEvents: .TouchDown)
        comment.addTarget(self, action: #selector(self.CloseMethod1(_:event:)), forControlEvents: .TouchDown)

        return cell

    }



 @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!) {
            selectedindex.removeObject(selectindex!)
           // call your firebase method for update database 
        }else{
              selectedindex.addObject(selectindex!)
          // call your firebase method for update database
        }
        self.tableview.reloadData()
    }

Output :

https://www.dropbox.com/s/ub7wln5y6hdw0sz/like%20button.mov?dl=0




回答3:


This is caused by reusing previous cells when scrolling and is the base mechanism of a table view.

You need to reset the state of your button on every call to cellForRowAtIndexPath.

Between let cell = ... and cell.starButton.addTarget you need to perform something like cell.starButton.deselect(), or .select(), based on the index path you're working on.



来源:https://stackoverflow.com/questions/40025473/button-state-activates-on-wrong-cells

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!