Boris-Em / BEMCheckBox

Tasteful Checkbox for iOS. (Check box)
MIT License
2.63k stars 287 forks source link

Checkboxes in UITableViewCell Objects #81

Closed ghost closed 6 years ago

ghost commented 6 years ago

So I'm creating a questionnaire app in which I have a UITableView with a custom Cell class that inherits from UITableViewCell, and it contains an additional checkbox attribute on top of the inherited ones. My problem is twofold.

Firstly, for whatever reason, the checkboxes will not render in the XCode interface builder. I'm running the latest versions of Swift and Xcode, and I installed via CocoaPods. Secondly, when the controller starts up some of the checkboxes are selected while others are not. As I scroll, some of them even change. Do you have any ideas as to what might be causing this?

ghost commented 6 years ago

Bear in mind that for a smaller number of cells such that all fit on the view without the need to scroll, I have absolutely no issue with the checkbox operations. I'm still unable to render them on the interface builder but everything works as expected.

chejarla-venkatesh commented 6 years ago

@mbrahimi617 Sir, have you found any solution for this. I don't know to record a touch event in UITableViews or UICollectionViews..

ghost commented 6 years ago

So I found some Podfile snippet to fix the issue with storyboards, however, I'm still facing the issues with checkboxes that change during scrolling. Any ideas why they're changing state while the UITableView scrolls?

chejarla-venkatesh commented 6 years ago

CheckBoxes are changing state because the TableView/CollectionView delegate method cellForRow/ItemAtIndexPath is called every time you scroll and as we use cells dequeue reusable property to create cells everyTime you scroll. So, new cells will be created for the part of the screen that is visible for your eye.

Explanation:

  1. Let say that the checkBox for every cell is in unchecked state for the first time the TableView loads
  2. When we changed the state of two checkBoxes to checked state
  3. Now if we scroll down the TableView the cells which you have seen the before will be removed and new cell are created for the part of the TableView which you can actually see (we have to keep in mind that the cells for which we have checked the checkBoxes and all the cells which we have seen before scrolling down no longer exist)
  4. Again we will change the state of the checkBox to checked for whichever cells you want and you scrolled the tableView to top the checkBoxes which you have checked before are not checked because they are the new cells and not the cells you have seen before
  5. And even if you scroll down again all cells are back to their normal state bcoz they are the new cells.

I hope this explanation helps you to understand why the state of the checkBoxes are changing when scrolling. You can also check this by putting a breakpoint in the delegate method cellForRow/ItemAtIndexPath..

ghost commented 6 years ago

@chejarla-venkatesh Ah I see what you're saying. So do you have any work around?

ghost commented 6 years ago

Probably best to keep an array or hashmap and check state, although it would be a bit cumbersome.

chejarla-venkatesh commented 6 years ago

@mbrahimi617 Yes, here the workaround I did to keep track of the checkBoxes. We have to create an array to store the checked cell indices and when we check a checkBox append the cell Index to the array and if we uncheck remove the index from the array and in the cellForRow/ItemAtIndexPath implement an if condition

  `if selectedCellIndices.contains(indexPath.item) {
         cell.checkBox.on = true
    } else {
         cell.checkBox.on = false
    }
    cell.checkBox.tag = indexPath.item`

But, there is a lil problem with BEMCheckBox as there is no way to record these touch events in TableViews and CollectionView (at-least I don't know how to) we can't add a target method to checkBox. So I had to place a button on top of the checkBox and remove its text and make it clear color and I created a target method for the button and it looks like this

`func saveCheckBoxState(cell: EditCell) {        
    if cell.checkBox.on == true {
        cell.checkBox.on = false
    } else {
        cell.checkBox.on = true
    }        
    if selectedCellIndices.contains(cell.checkBox.tag) {
        selectedCellIndices = selectedCellIndices.filter{$0 != cell.checkBox.tag}
    } else {
        selectedCellIndices.append(cell.checkBox.tag)
    }
    print("Status1 \(selectedCellIndices.sorted { $0 < $1 })")
}`

The only disadvantage by doing this is that you will lose the checkBox animations as the checkBox is behind a UIButton, except for that everything is working as expected.. This is workaround I did and not just by myself, I took some help from StackOverFlow. Please let me know if you find any other way to overcome this issue..