balbi
balbi

Reputation: 77

Using MVVM with dependency Injection and Storyboard

I have a viewController which is designed in one page of Storyboard and is the initial/main screen of the app. I'm trying to get some data from the api, then update a collectionView on my screen. I did get data before, but now I'm trying to build a MVVM structure in the app.

The way I tried to convert the app to MVVM is basically; building a ViewModel and initializing the ViewController with the ViewModel using dependency injection. You can see my dependency injection as below:

class ViewController: UIViewController {
    
//MARK: - Properties

private var viewModel: ViewControllerViewModel? = nil

//MARK: - Lifce Cycle

override func viewDidLoad() {
    super.viewDidLoad()
}
    
//    //MARK: - Init
init(with viewModel: ViewControllerViewModel) {
    self.viewModel = viewModel
    super.init(nibName: nil, bundle: nil)
}

required init?(coder: NSCoder) {
    super.init(coder: coder)
  }
}

But the problem is, my viewModel is not being initialized at all. I did put some breakpoints to init() of ViewModel, but they never get hit and ViewModel below never executes. What am I missing here in terms of MVVM design pattern?

class ViewControllerViewModel {

init() {

   }
}

NOTE: I'm calling the viewController on SceneDelegate as below. How can I initialize the ViewController with using storyboard as below?:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
    guard let _ = (scene as? UIWindowScene) else { return }

    DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
        self?.window?.rootViewController = UIStoryboard(name: "PopularMovies", bundle: nil).instantiateInitialViewController()
        self?.window?.makeKeyAndVisible()
    }
    
}

Pictures:

Main Storyboard Main StoryBoard Class

Upvotes: 2

Views: 669

Answers (1)

Lobont Andrei
Lobont Andrei

Reputation: 90

When using a Storyboard the coder init is called. Basically you are never calling your init.

You could pass the VM when creatinv the viewController like

let viewController = // init the VC
viewController.viewModel = viewModel // create the VM you want to pass here.

Upvotes: 1

Related Questions