I am at the stage of learning new swift and I designed my application as mvc design pattern. I went on an adventure to learn mvvm :D.
There are parts that I still don't understand. I learned that I need to transfer without using UIKit in the ViewModel part, but I couldn't figure out how to transfer it. I have to find the way to it. I have 10 Viewcontroller pages and I want to make them all according to mvvm.
I'm trying to convert my design from MVC to MVVM but i am getting this error how can i solve it?
BreedsViewController
import UIKit
import ProgressHUD
protocol BreedsViewControllerInterface: AnyObject {
func prepareCollectionView()
}
final class BreedsViewController: UIViewController {
@IBOutlet weak var categoryCollectionView: UICollectionView!
// main storyboard collection View adding (dataSource, delegate)
@IBOutlet weak var popularCollectionView: UICollectionView!
// main storyboard collection View adding (dataSource, delegate)
@IBOutlet weak var specialsCollectionView: UICollectionView!
// main storyboard collection View adding (dataSource, delegate)
private lazy var viewModel = BreedsVM()
// data, move mvvm
var categories: [DogCategory] = []
var populars: [Breed] = []
var downCategories:[Breed] = []
override func viewDidLoad() {
super.viewDidLoad()
viewModel.view = self
viewModel.viewDidLoad()
}
private func registerCell() {
categoryCollectionView.register(UINib(nibName: CategoryCollectionViewCell.identifier, bundle: nil), forCellWithReuseIdentifier: CategoryCollectionViewCell.identifier)
popularCollectionView.register(UINib(nibName: DogPortraitCollectionViewCell.identifier, bundle: nil), forCellWithReuseIdentifier: DogPortraitCollectionViewCell.identifier)
specialsCollectionView.register(UINib(nibName: DogLandscapeCollectionViewCell.identifier, bundle: nil), forCellWithReuseIdentifier: DogLandscapeCollectionViewCell.identifier)
}
}
extension BreedsViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
switch collectionView {
case categoryCollectionView:
return categories.count
case popularCollectionView:
return populars.count
case specialsCollectionView:
return downCategories.count
default: return 0
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
switch collectionView {
case categoryCollectionView:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CategoryCollectionViewCell.identifier, for: indexPath) as! CategoryCollectionViewCell
cell.setup(category: categories[indexPath.row])
return cell
case popularCollectionView:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: DogPortraitCollectionViewCell.identifier, for: indexPath) as! DogPortraitCollectionViewCell
cell.setup(breed: populars[indexPath.row])
return cell
case specialsCollectionView:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: DogLandscapeCollectionViewCell.identifier, for: indexPath) as! DogLandscapeCollectionViewCell
cell.setup(breed: downCategories[indexPath.row])
return cell
default: return UICollectionViewCell()
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == categoryCollectionView {
let controller = ListDogsViewController.instantiate()
controller.category = categories[indexPath.row]
navigationController?.pushViewController(controller, animated: true)
} else {
let controller = FavoriteDetailViewController.instantiate()
controller.breed = collectionView == popularCollectionView ? populars[indexPath.row] : downCategories[indexPath.row]
navigationController?.pushViewController(controller, animated: true)
}
}
}
extension BreedsViewController: BreedsViewControllerInterface {
func prepareCollectionView() {
registerCell()
ProgressHUD.show()
NetworkService.shared.fetchAllCategories { [weak self] (result) in
switch result {
case.success(let allBreed):
ProgressHUD.dismiss()
self?.categories = allBreed.categories ?? []
self?.populars = allBreed.populars ?? []
self?.downCategories = allBreed.downCategories ?? []
self?.categoryCollectionView.reloadData()
self?.popularCollectionView.reloadData()
self?.specialsCollectionView.reloadData()
case.failure(let error):
ProgressHUD.showError(error.localizedDescription)
}
}
}
}
BreedsVM
import Foundation
protocol BreedsVMInterface {
var view: BreedsViewControllerInterface? { get set }
func viewDidLoad()
func didSelectItemAt(indexPath: IndexPath)
}
final class BreedsVM {
weak var view: BreedsViewControllerInterface?
}
extension BreedsVM: BreedsVMInterface {
func didSelectItemAt(indexPath: IndexPath) {
}
func viewDidLoad() {
view?.prepareCollectionView()
}
}
For example, I want to apply didselectItemAt according to Mvvm. When I want to do this, I get the following error. How can I solve it?
Changed BreedsViewController
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
viewModel.didSelectItemAt(indexPath: indexPath)
}
Changed BreedsVM
import Foundation
protocol BreedsVMInterface {
var view: BreedsViewControllerInterface? { get set }
func viewDidLoad()
func didSelectItemAt(indexPath: IndexPath)
}
final class BreedsVM {
weak var view: BreedsViewControllerInterface?
var categories: [DogCategory] = []
var populars: [Breed] = []
var downCategories:[Breed] = []
}
extension BreedsVM: BreedsVMInterface {
func didSelectItemAt(indexPath: IndexPath) {
if collectionView == categoryCollectionView {
let controller = ListDogsViewController.instantiate()
controller.category = categories[indexPath.row]
navigationController?.pushViewController(controller, animated: true)
} else {
let controller = FavoriteDetailViewController.instantiate()
controller.breed = collectionView == popularCollectionView ? populars[indexPath.row] : downCategories[indexPath.row]
navigationController?.pushViewController(controller, animated: true)
}
}
func viewDidLoad() {
view?.prepareCollectionView()
}
}
BreedsVM's warnings and errors
Cannot find 'categoryCollectionView' in scope Cannot find 'collectionView' in scope Cannot find 'popularCollectionView' in scope