具有动画单元格的RXSwift + UITableView最终会闪烁重新加载

时间:2018-01-06 10:21:30

标签: ios swift uitableview rx-swift

我有以下问题。我使用RxSwift将我的数据源绑定到UITableView,如下所示:

self.presenter.posts
      .bind(to: self.tableView.rx.items(cellIdentifier: "ListPostsCell")) { index, model, cell in
        if let cell = cell as? ImagePostTableViewCell {
          cell.viewModel = model
          cell.actionButton.rx.action = self.action(for: model.postId, index: index)
        }
      }.disposed(by: self.bag)

当tableview到达数据源计数的末尾时,我请求更多数据并更新数据源(无限滚动),如下所示:

self.tableView.rx.willDisplayCell
      .map { $0.indexPath.item }
      .distinctUntilChanged()
      .withLatestFrom(self.presenter.posts) { (item, posts) -> Bool in
        return item == posts.count - 3
      }
      .filter { $0 }
      .withLatestFrom(self.presenter.posts)
      .map { UsersPosts.Request(after: $0.last?.postId) }
      .bind(to: self.usersPostsInteractor.receiveUsersPosts.inputs)
      .disposed(by: self.bag)

这很好用,我可以按预期滚动无限。问题出在我的细胞内:

class ImagePostTableViewCell: UITableViewCell {
  @IBOutlet weak var postImageView: UIImageView!
  @IBOutlet weak var haiScoreLabel: UILabel!
  @IBOutlet weak var lastVoteLabel: UILabel!
  @IBOutlet weak var actionButton: UIButton!
  @IBOutlet weak var activtiyIndicator: UIActivityIndicatorView!

  var bag: DisposeBag?

  var viewModel: ImagePostTableViewCellViewModel? {
    didSet {
      let bag = DisposeBag()

      guard let vm = viewModel else { return }

      vm.image.asDriver(onErrorJustReturn: UIImage())
        .drive(onNext: { image in
          self.updateAppearanceFor(image)
        }).disposed(by: bag)

      self.haiScoreLabel.text = vm.haiScoreText
      self.lastVoteLabel.text = vm.lastVoteText
      self.actionButton.setTitle(vm.actionLabelText, for: .normal)
      self.activtiyIndicator.startAnimating()
      self.bag = bag
    }
  }

  func updateAppearanceFor(_ image: UIImage?, animated: Bool = true) {
    DispatchQueue.main.async {
      if animated {
        UIView.animate(withDuration: 0.5) {
          self.displayImage(image)
        }
      } else {
        self.displayImage(image)
      }
    }
  }

  private func displayImage(_ image: UIImage?) {
    if let image = image {
      self.show(image: image)
    } else {
      self.hide()
    }
  }

  private func show(image: UIImage) {
    self.postImageView.image = image
    self.postImageView.alpha = 1.0
    self.haiScoreLabel.alpha = 1.0
    self.lastVoteLabel.alpha = 1.0
    self.activtiyIndicator.stopAnimating()
  }

  private func hide() {
    self.postImageView.image = nil
    self.postImageView.alpha = 0
    self.haiScoreLabel.alpha = 0
    self.lastVoteLabel.alpha = 0
    self.activtiyIndicator.startAnimating()
  }

  override public func prepareForReuse() {
    super.prepareForReuse()
    self.displayImage(.none)
    self.viewModel = nil
    self.bag = nil
  }
}

正如您所看到的那样,动画最终会出现超平滑的滚动行为 - 但由于数据源更新,每次重新加载动画都会启动,未更改的内容会因动画而闪烁。

最后我想避免为可见细胞重新加载,但我真的很绝望。

有任何提示吗?提前致谢!!!

0 个答案:

没有答案