更新第一个可见单元格的内容时,CollectionView 中的最后一个可见单元格消失

Last visible cell in CollectionView disappears when updating first visible cell's content

提问人:paprika 提问时间:8/8/2023 更新时间:8/8/2023 访问量:43

问:

我在使用 RxDataSources 时有一个奇怪的行为。我正在使用 .我在集合视图的每个单元格中都有一个按钮,它显示了一些内容。此内容通过库提供的内置动画显示。当列表的第一个单元格没有完全显示时,这意味着我已经滚动了一下,并且只显示了单元格的一部分,如果我点击按钮(位于单元格底部),屏幕上的最后一个可见单元格会消失并完全重新出现一秒钟。我相信这可能是由于库中的内置动画,但是,它看起来太像一个错误了。RxCollectionViewSectionedAnimatedDataSource

这是我如何实现的。数据源:

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)

我的 OfferSection 对象如下所示:

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
  }
}

我的对象符合文档中建议的 以及 。OfferEquatableIdentifiableType

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
    }
}

我在想,也许我做错了什么?

iOS 版Swift UIKIT RX-SWIFT RXDATASOURCES

评论


答:

0赞 Daniel T. 8/8/2023 #1

我在您展示的代码中看到许多问题,可能还有其他问题......

  • 你的写错了。删除它,让编译器为你编写它。Offer.==
  • 你无法使用新数据更新当前产品/服务,也无法将现有产品/服务替换为具有相同标识的新产品/服务。因此,DataSource 无法知道正在更新哪个产品/服务。移除并用于 .uniqueIdididentity
  • 我怀疑你的也写错了。将其移除并替换为:OfferSectiontypealias OfferSection = AnimatableSectionModel<String, Offer>

如果进行上述更改不能解决您的问题。使用更多信息更新问题。

由于上述问题,可能发生的情况是,数据源被迫为每次更新执行完整的数据重新加载(而不仅仅是更新已更改的特定单元格),并且您会看到其中的工件。

评论

0赞 paprika 8/8/2023
我使用的原因是,当重新加载列表并向上滚动时,滚动是滞后的......我在使用时遇到的同样问题。另一个原因是它不是唯一的,它是后端返回的值。通过按照您的建议进行修复,解决了此 SO 问题提出的问题。然而,滞后再次发生......另外,我不明白你的第三点。identityRxCollectionViewSectionedReloadDataSourceidid
0赞 Daniel T. 8/8/2023
您的服务器有多个具有相同 ID 的优惠?我对此表示严重怀疑。你所说的滞后应该通过其他一些方式来解决。第三点是删除你的结构,并使用我提供的代码来定义它。看看这是否有助于解决滞后问题,如果没有,请发布有关该问题的另一个问题。OfferSection
0赞 paprika 8/9/2023
好的,完成了!感谢您的时间和帮助。