首页 > 解决方案 > Cell's delegate is nil in didSelectItemAt

问题描述

I have a UICollectionViewCell with an item Desk. Desk has a Bool property that I want to change when a cell is tapped.

I'm trying to better familiarize myself with the delegate pattern, and want to avoid using something like a transparent button overlaid on the cell. I thought it would work to assign the cell's delegate in cellForItemAt and trigger the delegate method in didSelectItemAt, but the cell's delegate is nil when I check in didSelectItemAt.

Struct:

struct Desk: Equatable, Codable {
    var name: String
    var wasTouched: Bool = false
}

Protocol:

protocol TouchTheDesk: AnyObject {
    func youTouchedIt(cell: DeskCell)
}

Cell:

import UIKit

class DeskCell: UICollectionViewCell {
    @IBOutlet weak var deskLbl: UILabel!

    weak var delegate: TouchTheDesk?

    var desk: Desk? {
        didSet {
            updateViews()
        }
    }

    func updateViews() {
        self.deskLbl.text = desk?.name
    }
}

Conform VC to Protocol and define delegate method:

extension NotAShoppingListVC: TouchTheDesk {
    func youTouchedIt(cell: DeskCell) {
        if cell.desk?.wasTouched != nil {
            cell.desk!.wasTouched = !cell.desk!.wasTouched
        } else {
            cell.desk!.wasTouched = true
        }
        collectionView.reloadData()
    }
}

cellForItemAt:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as? DeskCell else {return UICollectionViewCell()}
    cell.desk = deskDealer.desks[indexPath.item]
    if cell.desk!.wasTouched { //assigned on line above
        cell.backgroundColor = .red
    } else {
        cell.backgroundColor = .green
    }
    cell.delegate = self
    return cell
}

didSelectItemAt:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as? DeskCell else {return}
    #warning("delegate is nil")
    cell.delegate?.youTouchedIt(cell: cell)
}

edit: If I call the delegate method directly in didSelectItemAt and pass in the cell, the indexPath for the cell is nil in the delegate method

标签: iosswiftuicollectionviewdelegatesuicollectionviewcell

解决方案


内部didSelectItemAt替换

 guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as? DeskCell else {return}

guard let cell = collectionView.cellForItem(at: indexPath) as? DeskCell else {return}

当您在其dequeueReusableCell外部使用时cellForItemAt,将返回与单击的单元格不同的单元格


推荐阅读