На основании этой статьи я создал многократно используемый источник данных для UICollectionView
следующим образом: -
final class CollectionViewDataSource<Model>: NSObject, UICollectionViewDataSource {
typealias CellConfigurator = (Model, UICollectionViewCell) -> Void
var models: [Model] = []
private let reuseIdentifier: String
private let cellConfigurator: CellConfigurator
init(reuseIdentifier: String, cellConfigurator: @escaping CellConfigurator) {
self.reuseIdentifier = reuseIdentifier
self.cellConfigurator = cellConfigurator
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return models.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let model = models[indexPath.item]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
cellConfigurator(model, cell)
return cell
}
}
Затем я расширил этот класс, чтобы я мог предоставить 'спецификацию ячейки c 'установка основана на типе модели
extension CollectionViewDataSource where Model == HomeFeedItem {
static func make(reuseIdentifier: String = "FEED_ARTICLE_CELL") -> CollectionViewDataSource {
return CollectionViewDataSource(reuseIdentifier: reuseIdentifier, cellConfigurator: { item, cell in
(cell as? FeedArticleCell)?.render(with: item)
})
}
}
extension CollectionViewDataSource where Model == HomeFeedAlertItem {
static func make(reuseIdentifier: String = "FEED_ALERT_CELL") -> CollectionViewDataSource {
return CollectionViewDataSource(reuseIdentifier: reuseIdentifier, cellConfigurator: { item, cell in
(cell as? FeedAlertCell)?.render(with: item)
})
}
}
Это работает отлично, однако каждая из этих ячеек имеет разный дизайн, но на самом деле принимает очень похожие свойства (как и другие ячейки) - из-за этого я думал о создании простого FeedItemModel
и сопоставлении этих свойств до отображения моего фида. Это гарантирует, что где бы я ни отображал элемент фида, я всегда имел дело с одними и теми же свойствами.
Имея это в виду, я пытался создать что-то вроде: -
extension CollectionViewDataSource where Model == FeedItemModel {
static func make(reuseIdentifier: String = "FEED_ARTICLE_CELL") -> CollectionViewDataSource {
return CollectionViewDataSource(reuseIdentifier: reuseIdentifier, cellConfigurator: { item, cell in
switch item.type {
case .news: (cell as? FeedArticleCell)?.render(with: item)
case .alert: (cell as? FeedAlertCell)?.render(with: item)
}
})
}
}
Это, однако, падает поскольку поле reuseIdentifier
больше не является правильным, если item.type
равно .alert
.
Как я могу реорганизовать этот шаблон, чтобы позволить мне использовать разные типы ячеек с одной и той же моделью? Или я должен отказаться от этого подхода и придерживаться другой модели для каждого типа ячеек, независимо от того, какие свойства ввода одинаковы?