-
Notifications
You must be signed in to change notification settings - Fork 593
Presenters
Presenters are mini controllers for your cells. They are responsible for registering cells in the UICollectionView
, provide heights for the layout and configure the cells itself.
public protocol ChatItemPresenterProtocol: class {
static func registerCells(collectionView: UICollectionView)
var canCalculateHeightInBackground: Bool { get } // Default is false
func heightForCell(maximumWidth width: CGFloat, decorationAttributes: ChatItemDecorationAttributesProtocol?) -> CGFloat
func dequeueCell(collectionView collectionView: UICollectionView, indexPath: NSIndexPath) -> UICollectionViewCell
func configureCell(cell: UICollectionViewCell, decorationAttributes: ChatItemDecorationAttributesProtocol?)
func cellWillBeShown(cell: UICollectionViewCell) // optional
func cellWasHidden(cell: UICollectionViewCell) // optional
func shouldShowMenu() -> Bool // optional. Default is false
func canPerformMenuControllerAction(action: Selector) -> Bool // optional. Default is false
func performMenuControllerAction(action: Selector) // optional
}
There's a 1-to-1 relationship between a ChatItemProtocol
and a Presenter
.
A Presenter
lives as long as its related ChatItemProtocol
is given to the BaseChatViewController
by the Data Source. See Update flow to know more about the conditions when a Presenter is reused after an update.
Presenters have to deal with cell reuse, as they will be given different cell instances as the user scrolls in the UICollectionView. However, a Presenter will always present the same message.
There's a convenient BaseChatItemPresenter<CellT: UICollectionViewCell>
that keeps track of the visible cell so you can forget about cell reuse.
Presenters are the place where your code executes. Therefore, we didn't want to impose any restrictions on their initializers, so we had to add another layer responsible for their creation.
public protocol ChatItemPresenterBuilderProtocol {
func canHandleChatItem(chatItem: ChatItemProtocol) -> Bool
func createPresenterWithChatItem(chatItem: ChatItemProtocol) -> ChatItemPresenterProtocol
var presenterType: ChatItemPresenterProtocol.Type { get }
}
A collection of PresenterBuilders must be given to the BaseChatViewController during the load process so we can register cells in the UICollectionView and create the Presenters to configure the cells.
public typealias ChatItemType = String
public func createPresenterBuilders() -> [ChatItemType: [ChatItemPresenterBuilderProtocol]] {
assert(false, "Override in subclass")
return [ChatItemType: [ChatItemPresenterBuilderProtocol]]()
}
Alternatively, you can override
public func createPresenterFactory() -> ChatItemPresenterFactoryProtocol {
// Default implementation
return ChatItemPresenterFactory(presenterBuildersByType: self.createPresenterBuilders())
}
And provide your own class to that creates Presenters, getting rid of the builders.
TL;DR
- 1-to-1 relationship with
ChatItemProtocol
and same life time. - 1-to-many relationship with
UICollectionViewCell
. Different cells may be given to the presenter as they are created or reused by the UICollectionView - Checkout
BaseChatItemPresenter
. It will hold a reference the visible cell so you can forget about cell reuse - Presenters are created by ChatItemPresenterBuilders where you can inject all your dependencies