skip to Main Content

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".

2

Answers


  1. 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 {
        ...
    }
    
    Login or Signup to reply.
  2. 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
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search