0

I have a protocol my TableView cell controllers conform too:

protocol TableViewCellController {
  func view(in tableView: UITableView) -> UITableViewCell
  func cancelLoad()
  func prefetch()
}

extension TableViewCellController {
  func prefetch() { }
}

As my table view renders multiple cell types, each type of item as its own controller


final class ContentArticleTitleCellController: TableViewCellController {

  private var cell: ContentArticleTitle?

  func view(in tableView: UITableView) -> UITableViewCell {
    cell = tableView.dequeueReusableCell()
    return cell!
  }
.....
}

final class ContentArticleSummaryCellController: TableViewCellController {

  private var cell: ContentArticleSummary?

  func view(in tableView: UITableView) -> UITableViewCell {
    cell = tableView.dequeueReusableCell()
    return cell!
  }
.....
}

As all of these controllers conform to Hashable, I'd like to use UITableViewDiffableDataSource.

I can create my data source using AnyHashable like so

  func makeDataSource() -> UITableViewDiffableDataSource<Section, AnyHashable> {
    return UITableViewDiffableDataSource(tableView: tableView) { tv, indexPath, controller -> UITableViewCell? in
      guard let controller = controller as? TableViewCellController else { return nil }
      return controller.view(in: tv)
    }
  }

I am unsure how to cast my [TableViewCellController] to [AnyHashable] however as TableViewCellController does not conform to it, rather the class that is conforming to it.

I had considered

  func update(with items: [TableViewCellController], animate: Bool = true) {
    let controllers = items.compactMap { $0 as? AnyHashable }
  }

But as these types are unrelated it always fails.

If I try

let controllers = items.compactMap { $0 as? Hashable }

I then hit the generic constraint because it has Self or associated type requirements

Of course I can do something like

let controllers = items.compactMap { $0 as? ContentArticleSummaryCellController }

But if I have 30 different cell controller types this becomes messy

How can I achieve this?

Teddy K
  • 820
  • 1
  • 6
  • 17

1 Answers1

-1

You were close with this approach:

let controllers = items.compactMap { $0 as? AnyHashable }

Change it to:

let controllers = items.map(AnyHashable.init)
Sander Saelmans
  • 831
  • 4
  • 13
  • thanks! This seems to produce the error `Value of protocol type 'TableViewCellController' cannot conform to 'Hashable'; only struct/enum/class types can conform to protocols` – Teddy K Aug 12 '20 at 09:12