Pradip Kumar Pradip Kumar - 4 months ago 22
Swift Question

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 tick and untick 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

}

}

}
}

Answer

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()
}