First I checked this post and it wasn't useful
I want to apply dependency injection on navigation from a controller to another,
let's say I have controller A :
import UIKit
class A: UIViewController {
}
and a controller B :
import UIKit
class B: UIViewController {
var name : String!
}
I'm navigating from A to B in this way :
let bViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "BVC")
as! B
bViewController.name = "HelloWorld"
self.navigationController?.pushViewController(bViewController, animated: true)
I want to convert my code in order to be using dependency injection through initializers.
can any one advice if this can be done, and if can be done how ??
thnx in advance.
It is impossible since you use Storyboards. When you instantiate ViewController from Storyboard through instantiateViewController method it uses required init?(coder aDecoder: NSCoder) initialiser.
If you want to use your custom initialiser, you need to get rid of Storyboards and create UIViewController only from code or from xib file. So you will be able to make this:
import UIKit
class B: UIViewController {
var name: String!
init(name: String) {
self.name = name
super.init(nibName: nil, bundle: nil) # or NIB name here if you'll use xib file
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
Also you need to provide init(coder...) since every UI element can be instantiate from Storyboard. But you can leave it with default super call, since you won't use it.
Another option is to use static method in ViewController from the post in beginning of your question. But in fact it also assigns variables after ViewController's initialisation.
So no DI through initialisers for now. I would suggest to use separate struct for all the data which need to be injected in VC. This struct will have all the necessary fields so you won't miss any of them. And you typical flow will be:
Data structvar data: Data!Starting with iOS13 Apple added functionality that allows us to do dependency injection at initialization.
You can do this by using a new method on UIStoryboard called instantiateViewController(identifier:creator:). You have to define your own init with the desired data and coder in the view controller to which you want to pass data and then call this init with the above mentioned method in the parent/presenting view controller.
See linked documentation and example below.
class ParentViewController: UIViewController {
@IBAction private func button() {
let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "ChildViewController") { coder in
return ChildViewController(coder: coder, userId: "123")
}
navigationController?.pushViewController(controller, animated: true)
}
}
class ChildViewController: UIViewController {
var userId: String
init?(coder: NSCoder, userId: String) {
self.userId = userId
super.init(coder: coder)
}
required init?(coder: NSCoder) {
fatalError("Missing user id.")
}
override func viewDidLoad() {
super.viewDidLoad()
print("UserId: \(userId)")
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With