iOS: MVVM-C ViewController super class

279 views Asked by At

I have MVVM-C arch. Each UIViewController has a ViewModel and CoordinatorDelegate to notify the Coordinator when navigation needs to be performed. The code that creates the VC repeats itself, and I thought it would be great to create a super class to unify all static funcs that create the VC. Like this:

import UIKit

class MVVMCViewController: UIViewController {
    
    weak var coordinatorDelegate: CoordinatorDelegate?
    var viewModel: Modelling?
    
    static func initVC(storyboard: Storyboard,
                       coordinatorDelegate: CoordinatorDelegate?,
                       viewModel: Modelling?) -> Self {
        let viewController = Self.instantiate(in: storyboard)
        viewController.coordinatorDelegate = coordinatorDelegate
        viewController.viewModel = viewModel
        return viewController
    }
}

All CoordinatorDelegateProtocols will inherit from CoordinatorDelegate and all ViewModels will be inheriting from Modelling.

But the subclassing does not work smoothly.

enter image description here

Any ideas?

2

There are 2 answers

1
Kstin On BEST ANSWER

Hi this model wouldn't work fine.

MVVMCViewController has hardcoded protocols as variable type, so You should have the same in your childVC.

To make it work as u want MVVMCViewController show be generic (but can be a lot of issues with it), like

class MVVMCViewController<T: Modelling, U: CoordinatorDelegate>: UIViewController {
    
    weak var coordinatorDelegate: U?
    var viewModel: T?

}

or add just casted properties to ConnectViewController

class ConnectViewController: MVVMCViewController {
    
    weak var coordinatorDelegate: CoordinatorDelegate?
    var viewModel: Modelling?
    var currentDelegate: ConnectViewControllerCoordinatorDelegate? {
         coordinatorDelegate as? ConnectViewControllerCoordinatorDelegate
    }
    var currentVM: ConnectViewModel? {
         viewModel as? ConnectViewModel
    }
}
0
Ravi Tripathi On

Your superclass MVVMCViewController defines two properties coordinatorDelegate and viewModel. If you just need to access them in your child class ConnectViewController, just access it normally. You don't need to define it again.

Also, in your parent class, you have weak var coordinatorDelegate: CoordinatorDelegate?. But in your child class (ConnectViewController), you redeclare the property with a different type (ConnectViewControllerCoordinatorDelegate?). That is illegal, even if it is a subclass of CoordinatorDelegate.

Hence, either

  1. Rename the property in child class to avoid the conflict
  2. Keep the name and the type, but add an override keyword for the property if you plan to add additional functionality in your child class
  3. Do not declare the property again at all in your child class if you don't need to add additional functionality to it. Just access it directly.

Refer to how inheritance works in Swift over here: https://docs.swift.org/swift-book/LanguageGuide/Inheritance.html