Reputation:
So I am making a custom subclass of UICollectionViewDiffableDataSource.
My code looks like this :
class MyDiffableDataSource: UICollectionViewDiffableDataSource<String, String> {
convenience required init(collectionView: UICollectionView) {
self.init(collectionView: collectionView) { (collection, index, item) in
if index.item % 2 == 0 {
return self.firstCell(collection, item, index)
} else {
return self.secondCell(collection, item, index)
}
}
self.supplementaryViewProvider = { (_, _, index) in
return self.header(collectionView, index)
}
}
func firstCell(_ collection: UICollectionView, _ item: String, _ index: IndexPath) -> UICollectionViewListCell {
let cellReg = UICollectionView.CellRegistration<UICollectionViewListCell, String> { (cell, _, item) in
var content = cell.defaultContentConfiguration()
content.text = item
cell.contentConfiguration = content
cell.accessories = [.disclosureIndicator()]
}
return collection.dequeueConfiguredReusableCell(using: cellReg, for: index, item: item)
}
func secondCell(_ collection: UICollectionView, _ item: String, _ index: IndexPath) -> UICollectionViewListCell {
let cellReg = UICollectionView.CellRegistration<UICollectionViewListCell, String> { (cell, _, item) in
var content = cell.defaultContentConfiguration()
content.text = item
cell.contentConfiguration = content
cell.accessories = [.checkmark()]
}
return collection.dequeueConfiguredReusableCell(using: cellReg, for: index, item: item)
}
func header(_ collection: UICollectionView, _ index: IndexPath) -> UICollectionReusableView {
let headerReg = UICollectionView.SupplementaryRegistration
<UICollectionReusableView>(elementKind: UICollectionView.elementKindSectionHeader) { (_, _, _) in }
return collection.dequeueConfiguredReusableSupplementary(using: headerReg, for: index)
}
}
But of course I get the 'self' used before 'self.init' call or assignment to 'self' error from Xcode.
How can I initialize MyDiffableDataSource only with a UICollectionView parameter without getting this error?
I know i can make the functions firstCell()
and secondCell()
static, or that i can put all the content of the two functions directly in the init. But that would not be great if i add more later and static would prevent me from accessing other non static properties.
Is there any other solutions that I can use?
Thanks!
Upvotes: 2
Views: 475
Reputation: 1
Maybe it will be useful to someone. I developed a protocol-based solution that does not require static methods for this problem.
protocol CellProviderRegistry {
associatedtype Cell: UICollectionViewCell
associatedtype Item
// Optional: Add the following line if you need dependency
// associatedtype Dependency
typealias CellRegistration = UICollectionView.CellRegistration<Cell, Item>
func callAsFunction(with dependency: Dependency) -> CellRegistration
}
// Simple example
struct WidgetCellProvider: CellProviderRegistry {
func callAsFunction(with dependency: DashboardViewModel) -> CellRegistration {
CellRegistration { cell, indexPath, item in
// Configure your cell
cell.backgroundColor = UIColor.clear
}
}
}
final class DashboardDiffableDataSource: UICollectionViewDiffableDataSource<Section, Item> {
private let cellRegistration = WidgetCellProvider()
init(collectionView: UICollectionView, dependency: DashboardViewModel) {
// Inside this block we call instance method `callAsFunction` while avoiding the static version
let provider = cellRegistration(with: dependency)
super.init(collectionView: collectionView) { collectionView, indexPath, item in
collectionView.dequeueConfiguredReusableCell(
using: provider,
for: indexPath,
item: item
)
}
}
}
Upvotes: 0