RxSwiftCommunity / RxDataSources

UITableView and UICollectionView Data Sources for RxSwift (sections, animated updates, editing ...)
MIT License
3.08k stars 493 forks source link

Support for UICollectionViewDelegateFlowLayout (sizeForItemAt) #335

Open hiddely opened 4 years ago

hiddely commented 4 years ago

Are there plans to support UICollectionViewDelegateFlowLayout in some reactive way, to respond to sizes based on the data model instead of only being able to rely on indexPath?

Currently, I'm doing something like this:

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        guard self.events?.count ?? 0 > indexPath.section,
            let item = self.events?[indexPath.section] else {
            return .zero
        }

        switch item {
        case .comingUp(items: _):
            return // something
        case .other(month: _, items: _):
            return CGSize(width: collectionView.bounds.width, height: CompactEventCollectionViewCell.cellHeight)
        case .otherFirst(month: _, items: _):
            return CGSize(width: collectionView.bounds.width, height: CompactEventCollectionViewCell.cellHeight)
        case .tips(items: _):
            return CGSize(width: collectionView.bounds.width, height: HorizontalTipCollectionViewCell.cellHeight)
        }
    }

However, this relies on some helper local variable events, which may or may not have been updated by an observable when the delegate is called.

cd5z commented 4 years ago

https://github.com/RxSwiftCommunity/RxDataSources/pull/350

lordzsolt commented 4 years ago

A slight improvement, though not the ideal solution: Both UICollectionView and UITableView expose func model<T>(at indexPath: IndexPath) throws -> T

So you could rewrite the top part to:

guard let item = try? collectionView.rx.model(at: indexPath) as YourModel else { 
    return .zero
}