Did取消选择屏幕外的单元格

DidDeselect cells off screen

我试图通过更改其边框和阴影颜色来显示 selected 单元格在我的 UICollectionView 中。我的问题是,如果我 select 一个单元格然后滚动屏幕的 selected 单元格和 select 另一个单元格,我的 DidDeselect 函数会导致崩溃,我知道那是因为我的DidDeselect 正在尝试删除 select 一个已重复使用的单元格,所以我的问题是:

如果单元格滚出屏幕后就不再可见,我该如何删除该单元格的边框

我的DidSelect:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath as IndexPath) as! PresentationCell
    cell.layer.borderColor = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)
    cell.layer.borderWidth = 3
    cell.layer.shadowColor = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)
}

我的DidDeSelect:

func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
    let cellItem = collectionView.cellForItem(at: indexPath) as! PresentationCell
    cellItem.layer.borderColor = UIColor.clear.cgColor
    cellItem.layer.borderWidth = 3
    cellItem.layer.shadowColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
 }

它在这一行崩溃:

let cellItem = collectionView.cellForItem(at: indexPath) as! PresentationCell

错误是:Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

我的理解是因为我先 selected 的单元格不再显示,因为我将它滚动到视图之外,然后 selected 了 [=] 底部的一个单元格19=]

我该如何解决这个问题?

提升你没有做正确的方法来达到你的要求

下面我建议如何实现您的要求。

在单元格方法中输入边框颜色和宽度

  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
       let cell = collectionView.dequeueReusableCell(withReuseIdentifier: 
      "id_PresentationCell", for: indexPath) as! PresentationCell
   if arrYourData[IndexPath.row].isSelected == true {
        cell.layer.borderColor = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)
        cell.layer.borderWidth = 3
        cell.layer.shadowColor = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)
  }
        
}
  

当点击 didSelected 时使 isSelected 在点击时为真,如下所示:

    func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
        self.arrYourData[IndexPath.row].isSelected = !self.arrYourData[IndexPath.row].isSelected 

**Reload your collection here**
     }

这是正确的行为。当您使用 dequeueReusableCell 时,单元格将被重用,并且内存仅分配给可见单元格。所以,如果你试图拉一个已经被释放的单元格,那么它会给你 nil.

在你的情况下,你需要有一些自定义实现,你可以在其中保留选择并应用逻辑。

以下是工作代码...

在顶部声明变量

var mySelection = -1

将此代码块用于其余逻辑

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
 {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
    cell.backgroundColor = .blue
    if mySelection == indexPath.row {
      applySelection(cell: cell, index: indexPath.row)
    } else {
      removeSelection(cell: cell, index: indexPath.row)
    }
    return cell
 }

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
 {
    mySelection = indexPath.row
    if let cell = collectionView.cellForItem(at: indexPath as IndexPath) 
    {
      applySelection(cell: cell, index: indexPath.row)
    }
 }

override func collectionView(_ collectionView: UICollectionView, 
 didDeselectItemAt indexPath: IndexPath) 
 {
    if let cellItem = collectionView.cellForItem(at: indexPath) 
    {
      removeSelection(cell: cellItem, index: indexPath.row)
    }
 }

func applySelection(cell: UICollectionViewCell, index: Int) {
      cell.layer.borderColor = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)
      cell.layer.borderWidth = 3
      cell.layer.shadowColor = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)
 }

func removeSelection(cell: UICollectionViewCell, index: Int) {
    cell.layer.borderColor = UIColor.clear.cgColor
    cell.layer.borderWidth = 3
    cell.layer.shadowColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
 }