I’m trying to use dependency injection with instantiateInitialViewController for the initial view controller in a storyboard. My goal is to inject a ViewModel into my ViewController when it is instantiated. However, my app crashes with the error Fatal error: init(coder:) has not been implemented. Here’s my setup:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateInitialViewController(creator: { coder in
ViewController(coder: coder, viewModel: ViewModel())
})
window?.rootViewController = viewController
window?.makeKeyAndVisible()
}
Here is the viewcontroller
final class ViewController: UIViewController {
private let viewModel: ViewModel
init?(coder: NSCoder, viewModel: ViewModel) {
self.viewModel = viewModel
super.init(coder: coder)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
viewModel.fetchUsers { users in
print(users)
}
}
}
The problem is that even though you are fetching the storyboard yourself and instantiating the initial view controller yourself...
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateInitialViewController(creator: { coder in
ViewController(coder: coder, viewModel: ViewModel())
})
... nevertheless, you forgot to prevent the runtime from independently fetching the storyboard and instantiating the initial view controller. Therefore, your initial view controller is being instantiated twice — and the first time, your init?(coder:)
override is called and you crash.
To fix the problem, just go into the Info.plist and delete the line that sets the storyboard as Main:
See that line that I've highlighted? Select it and hit Delete.
Now your app will launch successfully and you'll be doing the dependency injection you were aiming at.