Swift 2 - Fatal Error when `didDeselectItemAtIndex

2019-08-12 07:47发布

I have a UICollectionView where I use the function didSelectItemAtIndexPath to select a cell and change its alpha.

In the UICollectionView there are 12 cells.

In Order to take the deselected cells back to alpha = 1.0 I use the function didDeselectItemAtIndexPath.

So far the code works however, when I select a cell and I scroll the UICollectionView the app crashes on the line let colorCell : UICollectionViewCell = collectionView.cellForItemAtIndexPath(indexPath)! inside the deselect function with the error:

fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)

I think I need to reload the collection view but How can I reload and keep the cell selected?

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

        let colorCell : UICollectionViewCell = collectionView.cellForItemAtIndexPath(indexPath)!
        colorCell.alpha = 0.4
    }


    override func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {

        let colorCell : UICollectionViewCell = collectionView.cellForItemAtIndexPath(indexPath)!
        colorCell.alpha = 1.0
    }

2条回答
疯言疯语
2楼-- · 2019-08-12 08:34

Crash happened because the cell that you selected and scrolled out of the visible region of the screen had been reused for other cells in the collection view. Now, when you try to fetch that selected cell in didDeselectItemAtIndexPath using cellForItemAtIndexPath, it resulted in a crash.

To avoid crash, as mentioned by @Michael Dautermann, use optional binding to validate if the cell is nil and then set the alpha

func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
    if let cell = collectionView.cellForItemAtIndexPath(indexPath) {
        cell.alpha = 1.0
    }
}

In order to persist your selection state during scrolling, check the cell's selection state and set your alpha value accordingly when you dequeue your cell in cellForItemAtIndexPath method

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

    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath)

    if cell.selected {
        cell.alpha = 0.4
    }
    else {
        cell.alpha = 1.0
    }

    return cell
}
查看更多
ゆ 、 Hurt°
3楼-- · 2019-08-12 08:54

cellForItemAtIndexPath seems to be returning an optional, so why not do:

override func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
    if let colorCell = collectionView.cellForItemAtIndexPath(indexPath) {
       colorCell.alpha = 1.0
    }
}
查看更多
登录 后发表回答