Created
April 30, 2021 10:19
-
-
Save achernoprudov/39b725fd335785c15f985e9744209665 to your computer and use it in GitHub Desktop.
Feed Collection Container Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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