Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
172 views
in Technique[技术] by (71.8m points)

ios - Check Boxes in CollectionView are changing positions when scrolling

I have collectionView (3*3) with Images I am loading from server and I placed a checkBox in the top left corner of each cell so that I can select the cells and based on the selected cells I will get ids for the respective cells images(ids coming from server) and I am able do everything right. But, the problem is if there is are 20 images and if I check the 5 random cells which are loaded for the first time and when I scroll down to select other cells 5 other random checkBoxes are already checked and if I scroll up again some other 5 random cells are checked. It appears that the checked checkBoxes are changing positions because of the dequeue reusable property in the cellForItemAtIndexPath of UICollectionView DataSource method..

I have no Idea how to overcome this problem. Please help me If any one knows how to do this. I am posting below the code I wrote so far and some simulator screenshots for better understanding of the problem...

EditCertificatesViewController:

import UIKit
import Alamofire

protocol CheckBoxState {
    func saveCheckBoxState(cell: EditCertificateCell)
}

class EditCertificatesViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {

    @IBOutlet weak var certificatesCollectionView: UICollectionView!

    var certificatesArray = [Certificates]()

     override func viewDidLoad() {
         super.viewDidLoad()
         self.title = "Delete Certificates"
         navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
     }

     func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

         return certificatesArray.count
     }

     func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

         let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "editCertificate", for: indexPath)  as! EditCertificateCell
         if let certificateURL = URL(string: certificatesArray[indexPath.item].imagePath) {
             cell.certificateImage.af_setImage(withURL: certificateURL)
         }
         cell.certificateId.text = "(certificatesArray[indexPath.item].imageId)"
         cell.selectCertificate.customBox()
         if selectedCellIndex.contains(indexPath.item) {
             cell.selectCertificate.on = true
         } 
         else {
             cell.selectCertificate.on = false
         }
         cell.selectCertificate.tag = indexPath.item
         cell.checkState = self
         return cell
       }
}

extension EditCertificatesViewController: CheckBoxState {

    func saveCheckBoxState(cell: EditCertificateCell) {

        if cell.selectCertificate.on == true {
            cell.selectCertificate.on = false
        } 
        else {
            cell.selectCertificate.on = true
        }

        if selectedCellIndex.contains(cell.selectCertificate.tag) {
            selectedCellIndex = selectedCellIndex.filter{$0 != cell.selectCertificate.tag}
        } 
        else {
            selectedCellIndex.append(cell.selectCertificate.tag)
        }
        print("Status1 (selectedCellIndex.sorted { $0 < $1 })")
        //        certificatesCollectionView.reloadData()
    }
}

EditCertificateCell:

import UIKit

class EditCertificateCell: UICollectionViewCell {

    @IBOutlet weak var certificateImage: UIImageView!
    @IBOutlet weak var selectCertificate: BEMCheckBox!
    @IBOutlet weak var certificateId: UILabel!
    @IBOutlet weak var selectCertificateBtn: UIButton!

    var checkState: CheckBoxState?

    override func awakeFromNib() {
        super.awakeFromNib()
        self.selectCertificateBtn.addTarget(self, action: #selector(btnTapped(_:event:)), for: .touchUpInside)
    }

    @objc func btnTapped(_ sender: UIButton,event: UIEvent) {
        self.checkState?.saveCheckBoxState(cell: self)
    } 
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

CollectionView dequeue's your cell. To rid of this you need to maintain array of selected certificates. Follow below procedure.

  1. Create an array arrSelectedIndex : [Int] = []

  2. In cellForRow,

    • First check either current index in available in arrSelectedIndex or not? If yes, then make your cell as selected otherwise keep it uncheck.

    • Give tag to your check button as like this buttonCheck.tag = indexPath.item

  3. If you wanted to select images on check button action, do below.

    • Get the button tag let aTag = sender.tag
    • Now check wther this index is available in arrSelectedIndex or not? If yes then remove that index from from the arrSelectedIndex otherwise append that array.
    • reload your cell now.
  4. If you wanted to select images on didSelectItem instaead check button action, do below.

    • Now check wther this selected index (indexPath.item) is available in arrSelectedIndex or not? If yes then remove that index from from the arrSelectedIndex otherwise append that array.
    • reload your cell now.

As this procedure is lengthy so I can only explain you how to do this. If need further help then you can ask.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...