0
votes

Consider an example:

protocol CellConfigurator {
  var cellClass: UICollectionViewCell.Type {get}
  func configure(cell: UICollectionViewCell)
}

class AppleCell: UICollectionViewCell {
  let title = UILabel()
}

class AppleCellConfigurator: CellConfigurator {
  let cellClass: UICollectionViewCell.Type = AppleCell.self
  func configure(cell: UICollectionViewCell) {
    guard let cell = cell as? AppleCell else {return}
    cell.title.text = "AAPL"
  }
}

I can use the aforementioned pattern to encapsulate the actual type of the UICollectionViewCell, use it as follows (pseudocode):

func cellAt(indexPath: IndexPath) -> UICollectionViewCell {
  let configurator = configurators[indexPath]
  let cell = collectionView.dequeueReusableCell(identifier: String(describing: configurator.cellClass))
  configurator.configure(cell)
  return cell
}

I'm looking forward to getting rid of the necessity to type-cast the cell in every conforming to CellConfigurator, for example, using protocols with associated types:

protocol CellConfigurator {
  associatedtype Cell
  func configure(cell: Cell)
}

class AppleCell: UICollectionViewCell {
  let title = UILabel()
}

class AppleCellConfigurator: CellConfigurator {
  typealias Cell = AppleCell
  func configure(cell: Cell) {
    cell.title.text = "AAPL"
  }
}

However, I can't hold them together in an array due to an error: "Protocol 'SomeProtocol' can only be used as a generic constraint because it has Self or associated type requirements".

Is there any way to achieve the two goals:

  1. Having a function with UICollectionViewCell parameter type for any CellConfigurator?
  2. Having a concrete type inside the function of a particular configurator
1
I think you can create a generic base class that conform to CellConfigurator and then AppleCellConfigurator will inherit from that class.Kamran
@Kamran I think it's a good case for type erasure.Richard Topchii

1 Answers

0
votes

You can use associatedtype in you're CellConfigurator:

protocol CellConfigurator: class {
    associatedtype CellType where CellType: UICollectionViewCell

    func configure(cell: CellType)
}

class AppleCell: UICollectionViewCell {
    let title = UILabel()
}

class AppleCellConfigurator: CellConfigurator {
    typealias CellType = AppleCell

    func configure(cell: CellType) {
        cell.title.text = "AAPL"
    }
}