skip to Main Content

How to get the selected cells count and selected cells array from UICollectionView, I need to set the limit of selection. Below is my code which is not working. Please guide. Thanks

 func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
    let indexPaths = collectionView.indexPathsForSelectedItems!
        print(indexPaths)
    if let selectedItems = collectionView.indexPathsForSelectedItems {
                if selectedItems.count >= 3 {
                    collectionView.deselectItem(at: indexPath as IndexPath, animated: true)
                    return false
                }
            }
    return true
}

Above code when written in didSelect method returns only selected cell index but here just skip to last line

return true 

2

Answers


  1. You can use the shouldSelectItemAt delegate method from the UICollectionViewDelegate to achieve that:

    func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
        return collectionView.indexPathsForSelectedItems?.count ?? 0 <=  selectionLimit
    }
    

    A sample demo to demonstrate how it works:

    class ViewController : UIViewController {
        private var myCollectionView:UICollectionView?
        private var selectionLimit = 4
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let view = UIView()
            view.backgroundColor = .white
    
            let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
            layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
            layout.itemSize = CGSize(width: UIScreen.main.bounds.width * 0.7, height: 60)
    
            myCollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
            myCollectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "MyCell")
            myCollectionView?.backgroundColor = UIColor.white
    
            myCollectionView?.allowsMultipleSelection = true
            myCollectionView?.dataSource = self
            myCollectionView?.delegate = self
    
            view.addSubview(myCollectionView ?? UICollectionView())
    
            self.view = view
        }
    }
    extension ViewController: UICollectionViewDataSource {
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return 20
        }
    
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let myCell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath)
            myCell.backgroundColor = UIColor.blue
            return myCell
        }
    }
    extension ViewController: UICollectionViewDelegate {
    
        func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
            print("Did select a cell at (indexPath.row)")
            let itemsLeftToSelect = selectionLimit - (collectionView.indexPathsForSelectedItems?.count ?? 0)
            print("Have (itemsLeftToSelect) items to select")
        }
    
        func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
            print("Did deselect a cell at (indexPath.row)")
            let itemsLeftToSelect = selectionLimit - (collectionView.indexPathsForSelectedItems?.count ?? 0)
            print("Have (itemsLeftToSelect) items to select")
        }
    
        func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
            return collectionView.indexPathsForSelectedItems?.count ?? 0 <  selectionLimit
        }
    }
    

    When you reach the selection limit, shouldSelectItemAt will return false and didSelectItemAt function will not be called anymore. On the other hand if you click on the already selected cell, didDeselectItemAt will be called and you will be called, and you are able to select + 1 cell again, as the number of selected items will decrease with 1. See also the debug logs in the example.

    Login or Signup to reply.
  2. A better approach is model based.

    In your data model add a property

    var isSelected = false
    

    and re-/set it accordingly when a cell is de-/selected.

    Then you can simply count the selected data source items  – dataSource represents the data source array

    func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
        return dataSource.filter{$0.isSelected}.count < 3
    }
    

    Further there is no need to deselect a row in this method as you are preventing the user from selecting more than 2 rows.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search