iosswiftdesign-patternsmvvmuikit

MVVM Design pattern implementation


I am asking for the implementation of MVVM Design pattern so here i have a HomeViewController

Which contains a HomeViewModel , HomeViewController has a tableView and some other UIKit components in MVVM i read that Every UIView should have its own ViewModel so for the cells of UITableView (HomeTableViewCell) each one should hase its own ViewModel , so should HomeViewModel contains A Collection of SubViewModels for the cells that will be passed to every cell or what is the right implementation of it , the best scenario?

extension HomeViewController : UITableViewDelegate, UITableViewDataSource {
    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return viewModel?.articlesCount ?? 0
    }
        
    public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // ...
    }
}

Solution

  • i read that Every UIView should have its own ViewModel

    You're right but remember that get more & more deep to observe MVVM for every UIKit components can get complicated and it gets a lot of time! so my suggestion is always consider the project situation and deadlines.

    also, I suggest you to have code style. read about them, for example in your codes noticed that your class name start with lowercase myCell , which is not common.


    answer your question:

    remember this: UITableViewCell should not be accessible to the model.

    Add new View Model for MyCell:

    This is a basic view model to handle custom tableViewCell logic and data.

    class MyCellViewModel {
        private let model: CellModel
        init(model: CellModel) {
            self.model = model
        }
    }
    
    // properties TableViewCell needs.
    extension MyCellViewModel {
        var title: Any {
            return model.title
        }
    
        var someImage: Any {
            return model.image
        }
        // add variables or functions...
    
    }
    

    Update custom UITableViewCell, MyCell:

    add an optional variable to hold viewModel and when view model didSet, update views.

    class myCell: UITableViewCell {
        var viewModel: MyCellViewModel? {
            didSet {
                guard let viewModel = viewModel else { return }
    
                // just an example
                titleLabel.text = viewModel.title
            }
        }
    }
    

    Add in View Model of HomeViewController:

    Now we need to pass view model of custom UITableViewCell from controller's view model.

    func viewModelForCell(atIIndexPath: IndexPath) -> MyCellViewModel {
            return MyCellViewModel(model: articles[indexPath.row])
    }
    

    This basic implementation is just to show the MVVM concept of avoid view to access the model and handle all logical procedure in View Model, of course You can improve it and adopt it to your needs, happy coding!