I'm learning MVVM and RxSwift, and I want to display data from GitHub api and populate into collectionViewDiffableDataSource. But it's not displaying my data, even with my snapshot is already setup to accept my data. This is my code
class FollowersListViewModel {
let searchText = BehaviorRelay<String>(value: "")
let page = BehaviorRelay<Int>(value: 1)
var followers = BehaviorRelay<[FollowerViewModel]>(value: [])
var filterFollowers = BehaviorRelay<[FollowerViewModel]>(value: [])
let hasMoreFollower = BehaviorRelay<Bool>(value: false)
let isLoading = BehaviorRelay<Bool>(value: true)
private let manager: NetworkManager
let disposeBag = DisposeBag()
init(manager: NetworkManager) {
self.manager = manager
}
func fetchFollowers(with username: String) {
isLoading.accept(true)
searchText.asObservable()
.filter { $0.count > 2 }
.throttle(.seconds(3), scheduler: MainScheduler.instance)
.distinctUntilChanged()
.flatMapLatest { query in
self.manager.getFollowers(with: query, page: self.page.value)
}.subscribe { followers in
self.isLoading.accept(false)
self.followers.accept(followers.map { FollowerViewModel(follower: $0)})
print(self.followers.value)
} onError: { error in
print(error)
}.disposed(by: disposeBag)
}
}
class FollowersListVC: UIViewController {
var viewModel: FollowersListViewModel
enum Section { case main }
var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource<Section, FollowerViewModel>!
override func viewDidLoad() {
super.viewDidLoad()
setupViewController()
setupSearchController()
setupCollectionView()
setupCollectionViewDataSource()
viewModel.fetchFollowers(with: username)
setupSnapshot()
}
private func setupCollectionViewDataSource() {
dataSource = UICollectionViewDiffableDataSource<Section, FollowerViewModel>(collectionView: collectionView, cellProvider: { (collectionView, indexPath, follower) -> UICollectionViewCell? in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FollowersCell.reuseID, for: indexPath) as! FollowersCell
cell.set(followerVM: follower)
return cell
})
}
private func setupSnapshot() {
var snapshot = NSDiffableDataSourceSnapshot<Section, FollowerViewModel>()
snapshot.appendSections([.main])
snapshot.appendItems(viewModel.followers.value)
DispatchQueue.main.async { self.dataSource.apply(snapshot, animatingDifferences: true) }
}
}
I don't know why but it's like my snapshot is not being called, it's seems different when use in MVVM
Your
setupSnapshot()
function is being called before the values have been accepted intofollowers
. I haven't used aNSDiffableDataSourceSnapshot
yet, but you likely need to do something like this instead:The above uses this helper function. It's optional but I think the code looks cleaner when using it:
By the way...
BehaviorRelay
s should never bevar
, always declare them usinglet
.map
above should be put in yourviewModel
rather than here.