Reputation: 722
I am new to RXSwift. So basically I want to move to the right only when the last cell is visible in my collectionView, but the visibleIndexPaths always return an empty list, if I try to get the visibleIndexPaths at #1 it will work fine, but not work at #2
One possible reason is that after I updated the dataSource, the collectionView was informed to reloadData then at that time, I was trying to get the visibleIndexPaths before the loading finishes?
Partial code of ViewController
class PerfectDayDiaryPopUpContentViewController: UIViewController {
@IBOutlet weak var textView: UITextView!
@IBOutlet weak var imageCollectionView: UICollectionView!
private var viewModel: PerfectDayDiaryPopUpContentViewModel
private let disposeBag = DisposeBag()
func bind() {
self.viewModel.dataSource
.bind(to: self.imageCollectionView.rx.items) { (collectionView, row, image) -> UICollectionViewCell in
// #1 wroking well
print(self.imageCollectionView.indexPathsForVisibleItems)
return self.renderCell(collectionView: collectionView, row: row, image: image)
}
.disposed(by: self.disposeBag)
self.viewModel.dataSource
.subscribe { [weak self] images in
if self != nil, let images = images.element {
let lastImageIndexPath = IndexPath(row: images.count - 1, section: 0)
// #2 not working
let visibleIndexPaths = self!.imageCollectionView.indexPathsForVisibleItems
let shouldMoveToRight = visibleIndexPaths.contains(lastImageIndexPath)
if shouldMoveToRight {
self!.imageCollectionView.scrollToItem(at: lastImageIndexPath, at: .left, animated: true)
}
}
}
.disposed(by: self.disposeBag)
}
}
Partial code of action binding of delete button
cell.deleteButton.rx
.controlEvent(.touchUpInside)
.bind {
self.viewModel.lastImages = self.viewModel.images.value
var images = self.viewModel.images.value
images.remove(element: image)
self.viewModel.images.accept(images)
self.viewModel.upateDataSource()
self.imageCollectionView.layoutIfNeeded()
}
.disposed(by: self.disposeBag)
ViewModel
class PerfectDayDiaryPopUpContentViewModel: NewPopUpContentViewModel {
public let content: BehaviorRelay<String>
public let images: BehaviorRelay<[UIImage]>
public let dataSource: BehaviorRelay<[UIImage]>
public let addImageIdentifier: String = "AddNewImage"
public let addImage = UIImage(named: "AddImage-HD")!
public var lastImages: [UIImage] = []
private let dataManager = DiaryDataManager()
private let disposeBag = DisposeBag()
init() {
self.addImage.accessibilityIdentifier = self.addImageIdentifier
self.content = BehaviorRelay<String>(value: "")
self.images = BehaviorRelay<[UIImage]>(value: [UIImage]())
self.dataSource = BehaviorRelay<[UIImage]>(value: [self.addImage])
}
init(diary: Diary) {
self.addImage.accessibilityIdentifier = self.addImageIdentifier
self.content = BehaviorRelay<String>(value: diary.getContent())
self.images = BehaviorRelay<[UIImage]>(value: diary.getImages())
self.dataSource = BehaviorRelay<[UIImage]>(value: [self.addImage])
}
public func upateDataSource() {
let images = self.images.value
if images.count < 8 {
self.addImage.accessibilityIdentifier = self.addImageIdentifier
self.dataSource.accept(images + [self.addImage])
} else {
self.dataSource.accept(images)
}
}
public func saveDiary() {
self.dataManager.saveDiary(date: CustomDate.current, content: self.content.value, images: self.images.value)
}
}
Upvotes: 0
Views: 763
Reputation: 722
Ok, I figured it out, this issue is nothing about RXswift
I just added layoutIfNeeded() and it worked
self.viewModel.dataSource
.subscribe { [weak self] images in
UIView.animate(withDuration: 0.3) {
self?.imageCollectionView.layoutIfNeeded()
}
if self != nil, let images = images.element {
let lastImageIndexPath = IndexPath(row: images.count - 1, section: 0)
// #2 not working
let visibleIndexPaths = self!.imageCollectionView.indexPathsForVisibleItems
let shouldMoveToRight = visibleIndexPaths.contains(lastImageIndexPath)
if shouldMoveToRight {
self!.imageCollectionView.scrollToItem(at: lastImageIndexPath, at: .left, animated: true)
}
}
}
.disposed(by: self.disposeBag)
Upvotes: 1