frameworker
frameworker

Reputation: 412

Looking for a more general methode for dequeuing UITableViewCells

Researching about this topic I found following code:

protocol ReusableView {

      static var reuseIdentifier: String { get }
}

extension ReusableView {

       static var reuseIdentifier: String {
           return String(describing: self)
    }
}
extension UITableViewCell: ReusableView {}

extension UITableView {

func dequeueReusableCell<T: UITableViewCell>(for indexPath: IndexPath) -> T {
    guard let cell = dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as? T else {
        fatalError("Unable to Dequeue Reusable Table View Cell")
    }

    return cell
  }
}

Like here suggested

My problem is, despite all of the prototype cells defined within storyboard have unique ReuseIdentifiers, the T.reuseIdentifier is always the same: UITableViewCell.

Even when I define following code

class c1 : UITableViewCell {}
class c2 : UITableViewCell {}
class c3 : UITableViewCell {}

and assign c1,c2,c3 to three prototype cells, the return value still will be UITableViewCell. So the shown example seems a good way to generalize the topic but something is missing.

This my code calling for calling the dequeue method:

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

    let cell = tableView.dequeueReusableCell(for: indexPath)

    // Configure the cell...
    let place = places[indexPath.row]
    cell.textLabel?.text = place.name
    cell.detailTextLabel?.text = "\(place.timestamp)"
    return cell
}

Upvotes: 2

Views: 71

Answers (1)

Sweeper
Sweeper

Reputation: 274565

You need to specify what kind of table view cell you want when you call the method:

let cell: c1 = dequeueReusableCell(for: indexPath)

This is also mentioned in the later parts of the linked tutorial:

Remember that we leverage generics and type inference. We want to dequeue a WeatherDayTableViewCell instance, not a UITableViewCell instance. But how should the compiler know that we want to dequeue a WeatherDayTableViewCell instance? The compiler tries to infer the type of the cell constant we define in tableView(_:cellForRowAt:). It sees that we return cell from tableView(_:cellForRowAt:) and, by inspecting the method definition, it infers that cell should be of type UITableViewCell. The compiler is correct. The solution is very simple. When we declare the cell constant, we need to explicitly specify its type. The compiler then understands that the dequeueReusableCell(for:) method should return a WeatherDayTableViewCell instance.

Also, I think using String(describing: self) is a bad way of getting the class name. If self implements CustomStringConvertible and has a custom description property, this could break your code. A better way is to use:

return String(describing: Self.self)

Upvotes: 2

Related Questions