Search code examples
swiftuitableviewnibcustom-cell

Why my checkbox in custom cell shows different behaviour while selecting and scrolling in swift?


I have a xib view in which I took a tableView with a customcell xib. In this custom cell I have a checkbox button which behaves like check and uncheck using custom cell. But when ever I click the first cell checkbox as tick the multiple of 9th cell like 9th row cell, 18th row cell, .....also became ticked. and while scrolling the checkbox tick option is changing between cells. I am not able to know why this is happening..??

I have registered cell xib view as:

override func viewDidLoad() {
    super.viewDidLoad()
    //Register custom cell
    let nib = UINib(nibName: "CustomOneCell", bundle: nil)
    AddOnTableView.registerNib(nib, forCellReuseIdentifier: "addoncell")
   }
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return ADDONITEMS.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell:CustomOneCell = AddOnTableView.dequeueReusableCellWithIdentifier("addoncell") as! CustomOneCell
    let item: AddOnItems = ADDONITEMS[indexPath.row]
            cell.addOnName.text = item.name
            cell.addOnPrice.text = "£\(item.price!)"


    return cell
}

For checkbox I have added a custom class as below:

var isCheckedAddOnGlobal = Bool()
class AddOnCheckBox: UIButton {


let checkedImage = UIImage(named: "checkboxredtick.png")! as UIImage
let unCheckedImage =  UIImage(named:"checkbox untick.png")!as UIImage

//bool property
var ischecked:Bool = false{
    didSet{
        //print(ischecked)
        if ischecked == true{
            self.setImage(checkedImage, forState: .Normal)


        }else{
            self.setImage(unCheckedImage, forState: .Normal)
        }
    }
}

override func awakeFromNib() {
    self.addTarget(self, action:#selector(CheckBox.buttonClicked(_:)), forControlEvents: UIControlEvents.TouchUpInside)
    self.ischecked = false
}

func buttonClicked(sender: UIButton) {

    if (sender == self) {
        if ischecked == true{
            ischecked = false
            isCheckedAddOnGlobal = false

        }else{
            ischecked = true
            isCheckedAddOnGlobal = true

        }

    }

    }
 }

Solution

  • This is happening because you are reusing the TableViewCell, To solve your problem you can try something like this, first create an array of Int that give you selected row and use that array inside cellForRowAtIndexPath method.

    var selectedItems = [Int]()
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell:CustomOneCell = AddO nTableView.dequeueReusableCellWithIdentifier("addoncell") as! CustomOneCell
        let item: AddOnItems = ADDONITEMS[indexPath.row]
        cell.addOnName.text = item.name
        cell.addOnPrice.text = "£\(item.price!)"
        cell.checkBoxBtn.tag = indexPath.row
        if (selectedItems.contains(indexPath.row)) {
            cell.checkBoxBtn.setImage(UIImage(named:"checkbox untick.png"), forState: .Normal)
        }
        else {
            cell.checkBoxBtn.setImage(UIImage(named: "checkboxredtick.png"), forState: .Normal)
        }
        cell.checkBoxBtn.addTarget(self, action:#selector(self.buttonClicked(_:)), forControlEvents: UIControlEvents.TouchUpInside)
        return cell
    }
    
    func buttonClicked(sender: UIButton) {
         if (self.selectedItems.contains(sender.tag)) {
              let index = self.selectedItems.indexOf(sender.tag)
              self.selectedItems.removeAtIndex(index)
         }
         else {
              self.selectedItems.append(sender.tag)
         }
         self.tableView.reloadData()
    }