Skip to content

Instantly share code, notes, and snippets.

@achernoprudov
Created April 30, 2021 10:19
Show Gist options
  • Save achernoprudov/39b725fd335785c15f985e9744209665 to your computer and use it in GitHub Desktop.
Save achernoprudov/39b725fd335785c15f985e9744209665 to your computer and use it in GitHub Desktop.
Feed Collection Container Example
// MARK: - Data
protocol FeedItem {
}
struct ShareFeedItem: FeedItem {
let id: String
}
// MARK: - Delegates
/// Abstract common protocol for all CollectionDelegates
protocol FeedItemCollectionDelegate {
func canHandle(_ item: FeedItem) -> Bool
func cellForRow(indexPath: IndexPath, item: FeedItem) -> UIView
}
/// Typed collection delegate type.
protocol FeedTypedItemCollectionDelegate {
associatedtype Item: FeedItem
var cellsForRegistration: [UIView.Type] { get }
func cell(at indexPath: IndexPath, for item: Item) -> UIView
}
extension FeedTypedItemCollectionDelegate {
func wrapInAdapter() -> CollectionAdapter<Self> {
CollectionAdapter(delegate: self)
}
}
// MARK: - Real implementation
class FeedShareCollectionDelegate: FeedTypedItemCollectionDelegate {
var cellsForRegistration: [UIView.Type] = [
UILabel.self
]
func cell(at indexPath: IndexPath, for item: ShareFeedItem) -> UIView {
return UILabel()
}
}
// MARK: - Adapter implementation
struct CollectionAdapter<Delegate: FeedTypedItemCollectionDelegate>: FeedItemCollectionDelegate {
let delegate: Delegate
func canHandle(_ item: FeedItem) -> Bool {
item is Delegate.Item
}
func cellForRow(indexPath: IndexPath, item: FeedItem) -> UIView {
guard let typedItem = item as? Delegate.Item else {
preconditionFailure("Item \(item) cannot be cast to \(Delegate.Item.self)")
}
return delegate.cell(at: indexPath, for: typedItem)
}
}
// MARK: - Usage in container
class Container {
var delegates: [FeedItemCollectionDelegate] = [
FeedShareCollectionDelegate()
.wrapInAdapter()
]
var feedItems: [FeedItem] = [
ShareFeedItem(id: "foo"),
ShareFeedItem(id: "bar")
]
func cellForRow(indexPath: IndexPath) -> UIView {
let item = feedItems[indexPath.item]
for delegate in delegates where delegate.canHandle(item) {
return delegate.cellForRow(indexPath: indexPath, item: item)
}
preconditionFailure("Can't find FeedItemCollectionDelegate for \(item)")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment