简体   繁体   中英

Why is that? Button toggles the state on a custom cell whose background image is reused by other cells

Button on a custom cell to toggle the background image state, which is reused by other cells, should be reuse problem, but do not know how to solve? Can you give me some advice?

    @objc func LickCheck(_ sender:UIButton){
        //Toggle button background image
        if !sender.isSelected {
          //code
        }else{
         //code
        }
        sender.isSelected = !sender.isSelected

    }

       func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell : FoneCell  = tableView.dequeueReusableCell(withIdentifier: "Focid", for: indexPath) as! FoneCell;

        cell.xxBtn.tag = indexPath.row;

        cell.xxBtn.addTarget(self, action: #selector(LickCheck), for: UIControl.Event.touchUpInside);

        return cell;
        }

FoneCell.swift:

lazy var xxxBtn : UIButton = {
        let btn = UIButton();
        btn.setImage(UIImage.init(named: "love_18x18_"), for: UIControl.State.normal);
        btn.setImage(UIImage.init(named: "love_on_20x20_"), for: UIControl.State.selected)


        return btn;
    }();

This should be something like,

FoneCell.swift :

protocol FoneCellDelegate: class {
   func didSelectButton(atIndex: Int)
}

@IBOutlet var loveBtn: UIButton!

public weak var delegate: FoneCellDelegate?

func awakeFromNib() {
   super.awakeFromNib()
   loveBtn.addTarget(self, action: #selector(LickCheck), for: UIControl.Event.touchUpInside);
}

 @objc func LickCheck(_ sender:UIButton){
        //Toggle button background image
        if !sender.isSelected {
            addDate(sender.tag)
        }else{
            deleteDate(sender.tag)
        }
        sender.isSelected = !sender.isSelected
        delegate?.didSelectButton(atIndex: sender.tag)
    }

ViewController.swift

var buttonStates =  Array(repeating: false, count: 10)//if you need 10 rows

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return buttonStates.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell : FoneCell  = tableView.dequeueReusableCell(withIdentifier: "Focid", for: indexPath) as! FoneCell;

    cell.loveBtn.tag = indexPath.row;
    cell.loveBtn.isSelected = buttonStates[indexPath.row]
    cell.delegate = self // Implement protocol on cell's class. And update the value in buttonStates when state toggled
    return cell
}

func didSelectButton(atIndex: Int) {
      buttonStates[atIndex] = !buttonStates[atIndex]
      tableView.reloadData()
}

in override method of UITableViewCell

override func prepareForReuse() {
          super.prepareForReuse()
      //set default state here 
     self.imageView.image = nil
     self.toggleButton.isOn = false 
//.....
    }

or you can do the same in tableViewcellForRowAtIndexPath

 let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell

    //Set default behaviour here
    cell.imageView.image = nil 
    cell.toggleButton.isOn = false 
  ....
return cell 

PS you can make array in viewController for save the state of button selected. eg

let isSelectedArray = Array(repeating: false, count: 100)
@objc func LickCheck(_ sender:UIButton){
        //Toggle button background image
        let tag = sender.tag
        if !isSelectedArray[tag]{

          //code
        }else{
         //code
        }
        isSelectedArray[tag] = !isSelectedArray[tag]
        sender.isSelected = !sender.isSelected
  }

I've solved the problem, First, define an array of global records that clicked over the button

    lazy var numbercells:[Int] = []

Secondly, in the

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell : FoneCell  = tableView.dequeueReusableCell(withIdentifier: "Focid", for: indexPath) as! FoneCell;

        if self.numbercells.contains(indexPath.row){
            cell.loveBtn.isSelected = true;
        }else{
            cell.loveBtn.isSelected = false;

        }
        cell.loveBtn.addTarget(self, action: #selector(LickCheck), for: UIControl.Event.touchUpInside);
        cell.loveBtn.tag = indexPath.row;

        return cell;

    }

The last

    @objc func LickCheck(_ sender:UIButton){

        if !sender.isSelected {
            self.numbercells.append(sender.tag);
            addDate(sender.tag)
        }else{
            self.numbercells = self.numbercells.filter(){$0 != sender.tag}
            deleteDate(sender.tag)
        }
        let posinton = IndexPath(row: sender.tag, section: 0);
        self.tableView.reloadRows(at: [posinton], with: UITableView.RowAnimation.none)

    }

This solves the button select state reuse problem on the cell

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM