【发布时间】:2020-01-16 08:12:38
【问题描述】:
基于此article,我为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
}
}
然后我扩展了这个类,因此我可以根据模型的类型提供“特定于单元格”的设置
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)
}
})
}
}
但是,如果 item.type 是 .alert,则 reuseIdentifier 字段不再正确,因此这会下降。
如何重构此模式以允许我在同一模型中使用不同的细胞类型?或者我应该放弃这种方法并为每种细胞类型坚持不同的模型,而不管输入属性是否相同?
【问题讨论】:
-
您的模型是否等于 .alert 的 FeedItemModel?
-
是的,我
FeedItemModel是一个通用模型,我正在将每种模型类型的相关值映射到该模型,因此提要项目只需要使用FeedItemModel,而不管它们的类型 -
好的,什么意思是“但是由于reuseIdentifier 字段不再正确,所以这会下降”,你这里有崩溃吗?还是错误的标识符?
-
标识符错误,因为每个单元格都注册了自己的标识符,所以重复使用
FeedArticleCell和FeedAlertCell使用值make(reuseIdentifier: String = "FEED_ARTICLE_CELL")- 因为它们是我想设置的不同单元格reuseIdentifier基于每个模型具有的item.type。 -
它不会崩溃,而只是呈现错误的单元格类型,因为我认为它使用
reuseIdentifier来准备单元格。
标签: ios swift uicollectionview uicollectionviewcell uicollectionviewdelegate