【问题标题】:Data not display in collectionView DiffableDataSource MVVM RxSwift数据未在 collectionView DiffableDataSource MVVM RxSwift 中显示
【发布时间】:2021-08-24 04:19:14
【问题描述】:

我正在学习 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 { $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) }
    }
}

我不知道为什么,但它就像我的快照没有被调用,在 MVVM 中使用时似乎不同

【问题讨论】:

    标签: swift mvvm rx-swift uicollectionviewdiffabledatasource nsdiffabledatasourcesnapshot


    【解决方案1】:

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

    func setupSnapshot() {
        viewModel.followers
            .map { (followers) in
                with(NSDiffableDataSourceSnapshot<Section, FollowerViewModel>()) {
                    $0.appendSections([.main])
                    $0.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 声明它们。
    • 像这样过度使用 BehaviorRelay 是一种代码异味。
    • 上面的map 应该放在你的viewModel 而不是这里。

    【讨论】:

    • 嘿丹尼尔感谢您的解决方案,它就像一个魅力:)。顺便说一句,如果我将地图放在我的 viewModel 中,那么我必须为 UICollectionViewDiffableDataSource 导入 UIKit 对吗?我听说,在 viewModel 中导入 UIKit 不是一个好主意
    • 导入 UIKit 没问题。请注意您从中使用的内容。使用其中的structs 和不可变类都很好。关键是逻辑在视图模型中,而副作用留在视图控制器中。
    猜你喜欢
    • 2014-10-26
    • 2020-02-21
    • 1970-01-01
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多