数据未显示在 collectionView DiffableDataSource MVVM RxSwift 中

Data not display in collectionView DiffableDataSource MVVM RxSwift

我正在学习 MVVM 和 RxSwift,我想显示来自 GitHub api 的数据并填充到 collectionViewDiffableDataSource 中。但它没有显示我的数据,即使我的快照已经设置为接受我的数据。这是我的代码

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 { [=10=].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: [=10=])})
                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) }
    }
}

不知道为什么好像我的快照没有被调用,用在MVVM里好像不一样

您的 setupSnapshot() 函数在值被 followers 接受之前被调用。我还没有使用过 NSDiffableDataSourceSnapshot,但你可能需要做这样的事情:

func setupSnapshot() {
    viewModel.followers
        .map { (followers) in
            with(NSDiffableDataSourceSnapshot<Section, FollowerViewModel>()) {
                [=10=].appendSections([.main])
                [=10=].appendItems(followers)
            }
        }
        .observe(on: MainScheduler.instance)
        .subscribe(onNext: { [dataSource] snapshot in
            dataSource.apply(snapshot, animatingDifferences: true)
        })
        .disposed(by: disposeBag)
}

上面使用了这个辅助函数。它是可选的,但我认为使用它时代码看起来更清晰:

func with<T>(_ value: T, _ fn: (inout T) -> Void) -> T {
    var temp = value
    fn(&temp)
    return temp
}

顺便说一句...

  • BehaviorRelays 永远不应是 var,始终使用 let.
  • 声明它们
  • 像这样过度使用 BehaviorRelays 是一种代码味道。
  • 上面的 map 应该放在你的 viewModel 而不是这里。