kacper99
kacper99

Reputation: 157

Dequeue multiple cells conforming to same protocol

I have a table view with 2 different cells. Both cells conform to same protocol "WorkoutCellProtocol" and I want to avoid rewriting same code during dequeuing. Probably there will more cells in the future, but each will conform to same protocol.

First cell is WorkoutCell with identifier: "WorkoutTableViewCell" Second cell is CardioCell with identifier: "CardioTableViewCell"

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        var cell: WorkoutCellProtocols!
        cell.delegate = self
        cell.editableRowBorders = colorEditable
        cell.numberOfCell = indexPath.row
        cell.numberOfExercise = indexPath.section
        cell.configureTextFields(model: 
        exercises[indexPath.row])
        
        if data[indexPath.row].category == "Cardio" {
            
            cell = tableView.dequeueReusableCell(withIdentifier: "CardioTableViewCell", for: indexPath) as! CardioTableViewCell
            return cell as! CardioTableViewCell
            
        } else {
            cell = tableView.dequeueReusableCell(withIdentifier: "WorkoutTableViewCell") as! WorkoutTableViewCell
            return cell as! WorkoutTableViewCell
        }
    }

When I try to do this in this way, so assign properties only once at the top, before assigning a class types I get "Unexpectedly found nil while implicitly unwrapping an Optional value".

Upvotes: 0

Views: 186

Answers (2)

Sweeper
Sweeper

Reputation: 274565

Dequeue your cell first, then configure it:

var cell: WorkoutCellProtocols

if data[indexPath.row].category == "Cardio" {
    cell = tableView.dequeueReusableCell(withIdentifier: "CardioTableViewCell", for: indexPath) as! WorkoutCellProtocols
} else {
    cell = tableView.dequeueReusableCell(withIdentifier: "WorkoutTableViewCell") as! WorkoutCellProtocols
}

cell.delegate = self
cell.editableRowBorders = colorEditable
cell.numberOfCell = indexPath.row
cell.numberOfExercise = indexPath.section
cell.configureTextFields(model: exercises[indexPath.row])
return cell

I'm assuming that your protocol is declared like this:

protocol WorkoutCellProtocols: UITableViewCell {
    ...
}

Upvotes: 2

Mark Thormann
Mark Thormann

Reputation: 2617

You can't do what you are trying to do with any implicitly unwrapped optional. Try moving the assignments down below the if block and type the cell to the protocol like this

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    var cell: WorkoutCellProtocols!
    
    if data[indexPath.row].category == "Cardio" {
        cell = tableView.dequeueReusableCell(withIdentifier: "CardioTableViewCell", for: indexPath) as! CardioTableViewCell
    } else {
        cell = tableView.dequeueReusableCell(withIdentifier: "WorkoutTableViewCell") as! WorkoutTableViewCell
    }

    guard let workoutCell = cell as WorkoutCellProtocols! else { fatalError("Unexpected cell type") }
    workoutCell.delegate = self
    workoutCell.editableRowBorders = colorEditable
    workoutCell.numberOfCell = indexPath.row
    workoutCell.numberOfExercise = indexPath.section
    workoutCell.configureTextFields(model: exercises[indexPath.row])
    return workoutCell
}

Upvotes: 0

Related Questions