21

I have a FollowVC and FollowCell Setup with collection View. I can display all the datas correctly into my uIcollection view cell using the following code with no problem.

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

    if let cell = collectionView.dequeueReusableCellWithReuseIdentifier("FollowCell", forIndexPath: indexPath) as? FollowCell {

        let post = posts[indexPath.row]

        cell.configureCell(post, img: img)

        if cell.selected == true {
            cell.checkImg.hidden = false
        } else {
            cell.checkImg.hidden = true
        }
        return cell
    }
}

Note that I could also select and deselect multiple images using the following code

    func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

    if deletePressed == true {
        let cell = collectionView.cellForItemAtIndexPath(indexPath) as! FollowCell
        cell.checkImg.hidden = false
    } else {
        let post = posts[indexPath.row]
        performSegueWithIdentifier(SEGUE_FOLLOW_TO_COMMENTVC, sender: post)
    }
}

func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
    let cell = collectionView.cellForItemAtIndexPath(indexPath) as! FollowCell
    cell.checkImg.hidden = true
}

When In "Select" mode, I can perform the selction of each cell and a check mark will be displayed on the cell. However, what I want to do is to have a cancel buttom to disable all the selected cell and removing the checkImg.

I have tried

    func clearSelection() {
    print("ClearSelection posts.count = \(posts.count)")

    for item in 0...posts.count - 1 {
        let indexP = NSIndexPath(forItem: item, inSection: 0)
        followCollectionView.deselectItemAtIndexPath(indexP, animated: true)
        let cell = followCollectionView.cellForItemAtIndexPath(indexP) as! FollowCell
        cell.checkImg.hidden = true
    }
}

The program crashes here giving me a fatal error: Unexpectedly found nil while unwrapping an optional error at

let cell = followCollectionView.cellForItemAtIndexPath(indexP) as! FollowCell

I dont know why it is having trouble unwrapping the cell to be my FollowCell which contains an instance of the checkImg. I already used it before in a similar situation in didSelectItemAtIndexPath and it seems to work?

Thanks,

Hugo
  • 1,106
  • 15
  • 25
user172902
  • 3,541
  • 9
  • 32
  • 75

6 Answers6

34

Not all of the selected cells may be on screen at the point when you are clearing the selection status, so collectionView.cellForItemAtIndexPath(indexPath) may return nil. Since you have a force downcast you will get an exception in this case.

You need to modify your code to handle the potential nil condition but you can also make your code more efficient by using the indexPathsForSelectedItems property of UICollectionView

 let selectedItems = followCollectionView.indexPathsForSelectedItems
 for (indexPath in selectedItems) {
     followCollectionView.deselectItemAtIndexPath(indexPath, animated:true)
     if let cell = followCollectionView.cellForItemAtIndexPath(indexPath) as? FollowCell {
        cell.checkImg.hidden = true
     }
 }
Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • Thanks. Exactly what I needed and works. I didnt need to use any reloadItems Code though. I did what you said and it works exactly like you said. – user172902 Jul 18 '16 at 08:03
  • 3
    Or, if you like it more swifty: `tableView.indexPathsForSelectedRows?.forEach({ tableView.deselectRow(at: $0, animated: false) })` – ersjoh Jun 01 '18 at 16:40
18

Using Extension in Swift 4

extension UICollectionView {

    func deselectAllItems(animated: Bool) {
        guard let selectedItems = indexPathsForSelectedItems else { return }
        for indexPath in selectedItems { deselectItem(at: indexPath, animated: animated) }
    }
}
Sangwon Park
  • 454
  • 5
  • 4
5

To simplify further, you could just do

followCollectionView.allowsSelection = false
followCollectionView.allowsSelection = true

This will in fact correctly clear your followCollectionView.indexPathsForSelectedItems even though it feels very wrong.

3
collectionView.indexPathsForSelectedItems?
    .forEach { collectionView.deselectItem(at: $0, animated: false) }
nslllava
  • 589
  • 2
  • 9
  • 19
0

This answer may be useful in swift 4.2

 let selectedItems = followCollectionView.indexPathsForSelectedItems

 for (value in selectedItems) {
     followCollectionView.deselectItemAtIndexPath(value, animated:true)
     if let cell = followCollectionView.cellForItemAtIndexPath(value) as? FollowCell {
        cell.checkImg.hidden = true
     }
 }
Ankur Purwar
  • 275
  • 2
  • 9
0

I got it solved easier by doing this:

 tableView.selectRow(at: nil, animated: true, scrollPosition: UITableView.ScrollPosition.top)
Thur Brum
  • 53
  • 1
  • 8