I have a weird behavior using RxDataSources. I am using an RxCollectionViewSectionedAnimatedDataSource
. I have a button inside each cell in the collection view, which reveals some content. This content is displayed through the built-in animations the library provides. When the first cell of the list is not appearing entirely, which means I've scrolled a bit and only part of the cell is showing, if I tap on the button (located at the bottom of the cell), the last visible cell on the screen disappears and reappears entirely for a quick second. I believe this might be due to the built-in animations in the library, however, it looks too much like a bug.
Here is how I have implemented things. The data source:
let dataSource = RxCollectionViewSectionedAnimatedDataSource<OfferSection>(
animationConfiguration: AnimationConfiguration(insertAnimation: .none, reloadAnimation: .none, deleteAnimation: .none), configureCell: {
[unowned self] dataSource, collectionView, indexPath, element in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: OfferCollectionViewCell.identifier, for: indexPath) as! OffersCollectionViewCell
cell.set(offer: element)
cell.findOfferButton.rx.tap.map{indexPath}.compactMap{$0}.map{ index in
(element, index.row)}.bind(to: self.viewModel.input.viewOffer).disposed(by: cell.disposeBag)
cell.redeemButton.rx.tap.map{element}.bind(to: self.viewModel.input.redeemOffer).disposed(by: cell.disposeBag)
return cell
})
viewModel.output.offers.map{ [OfferSection(header: "", items: $0)] }.drive(self.offersCollectionView.rx.items(dataSource: dataSource)).disposed(by: disposeBag)
My OfferSection object looks like this:
struct OfferSection: AnimatableSectionModelType {
var header: String
var items: [Offer]
var identity: Int {
return 0
}
}
extension OfferSection {
typealias Identity = Int
typealias CustomDataAlias = Offer
init(original: OfferSection, items: [Offer]) {
self = original
self.items = items
}
}
My Offer
object conforms to Equatable
as well as IdentifiableType
, as advised in the docs.
struct Offer: IdentifiableType, Equatable {
let id: Int?
let name: String
let path: String?
let offerLocation: String
let email: String?
let section: String
let categories: [String]
let uniqueId = UUID().uuidString
var identity: String {
return uniqueId
}
static func == (lhs: Offer, rhs: Offer) -> Bool {
lhs.id == rhs.id && lhs.name == rhs.name && lhs.offerLocation == rhs.offerLocation
}
}
I am wondering, maybe I have done something wrong?
I see a number of problems in the code you show, likely there are others...
Offer.==
is written incorrectly. Remove it and let the compiler write it for you.uniqueId
and use id
for the identity
.OfferSection
is also written incorrectly. Remove it and replace with: typealias OfferSection = AnimatableSectionModel<String, Offer>
If making the above changes doesn't fix your problem. Update the question with more information.
Because of the problems above, what is likely happening is that the data source is forced to do a complete data reload for every update (rather than just updating the specific cells that have changed) and you are seeing artifacts from that.