使用MVVM模式处理具有多个原型单元格的集合视图

3
我们目前正在为一个项目建立架构,我很难想象出完整的解决方案来解决这个问题。目前,我们有一个带有多个动态原型的集合视图,并且我们为每个单元格子类化其中一个。我想知道是否有一种方法可以做类似于以下的事情。
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    var cell = collectionView.dequeueReusableCell(withReuseIdentifier: viewModel.reuseIdentifierForIndexPath(indexPath), for: indexPath)
    //update cell here in a generic way based on the class of this cell (we have this information)
    return cell
}

基本上,我们想避免做以下这些事情:

if indexPath.row == 0 { 
//do stuff for this specific cell 
}

在像collectionView(_:cellForItemAt :) / collectionView(_:didSelectItemAt :)这样的方法中,同时遵循MVVM模式。
1个回答

3

您可以使用MVVM模式来处理单元格本身。因此,每个单元格都将拥有自己的viewModel。然后您可以使用类似下面的代码:

class ViewModel {

    func reuseIdentifier(for indexPath: IndexPath) -> String {
        //...
    }

    func cellViewModel(for indexPath: IndexPath) -> BaseCellViewModel {
        //...
    }

}

class BaseCellViewModel {
    //...
}

class CellAViewModel: BaseCellViewModel {
    //...
}

class CellBViewModel: BaseCellViewModel {
    //...
}

class CellA: UICollectionViewCell {
    var viewModel: CellAViewModel! {
        didSet {
            //update UI
        }
    }
}

class CellB: UICollectionViewCell {
    var viewModel: CellBViewModel! {
        didSet {
            //update UI
        }
    }

}

class ViewController: UIViewController {

    //...

    var viewModel: ViewModel = ViewModel()

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let reuseIdentifier = viewModel.reuseIdentifier(for: indexPath)
        let cell =
        collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
        //update cell here in a generic way based on the class of this cell (we have this information)
        configure(cell: cell, indexPath: indexPath)
        return cell
    }

    func configure(cell: UICollectionViewCell, indexPath: IndexPath) {
        switch cell {
        case let cell as CellA:
            cell.viewModel = viewModel.cellViewModel(for: indexPath) as! CellAViewModel
        case let cell as CellB:
            cell.viewModel = viewModel.cellViewModel(for: indexPath) as! CellBViewModel
        default:
            fatalError("Unkown cell type")
        }
    }

    //...

}

事实上,单元格(即视图)应该完全与viewModel解耦,不是吗? - Pavalache Alexandru
@PavalacheAlexandru,您还可以采用基于协议的方法,使您的视图模型实现协议,以便您的单元格/视图控制器依赖于协议而不是类实现(对于模拟非常有用)。但这可能会给代码增加很多复杂性,具体是否有用取决于您的应用程序需求。 - marosoaie
1
@PavalacheAlexandru 如果你将所有东西解耦,如果你后来想要给你的单元格添加一个标签,你就必须改变很多类:viewModel协议、viewModel实现、测试、模拟viewModel等等... - marosoaie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接