Hello, I have the following case:
protocol ViewProtocol {
func foo()
}
class AViewController: UIViewController, ViewProtocol {
public var b: B?
}
class B {
private let view: ViewProtocol
init(view: ViewProtocol) {
self.view = view
}
}
Can you please tell me how should I resolve those 2 dependencies? I tried to follow the example from here but I couldn't manage to do it.
Note: AViewController is the initial ViewController in the main storyboard.
Thank you in advance,
Alin
Hi @alynmuntean,
Are you using SwinjectStoryboard for your AViewController, or creating it via init? Could you post the Swinject code you've tried and did not work?
Hello @jakubvano,
Yes, I am using SwinjectStoryboard for AViewController, which is also the initial view controller in the Storyboard. I don't have that code anymore because I did try many options and I ended up with one that I'm not very sure it is the good one. Could you please check the solution and maybe give me a feedback if it is ok or not?
extension SwinjectStoryboard {
class func setup() {
defaultContainer.registerForStoryboard(AViewController.self) { resolver, controller in
let b = B(view: controller)
controller.b = b
}
defaultContainer.register(B.self) { resolver in
return resolver.resolve(AViewController.self)!.b!
}
}
}
Thank you!
Unfortunatelly, SwinjectStoryboard does not support circular dependencies - as stated here you cannot directly call resolve for view controllers initialised from storyboard - thus with your current setup resolver.resolve(AViewController.self)! will fail.
Also, with your current setup there will be retain cycle between B and AViewController - at least one of the references should be weak.
When I need circular dependency with UIViewController I typically use this setup:
protocol ViewProtocol: class {}
class ViewController: UIViewController, ViewProtocol {
var presenter: Presenter?
}
class Presenter {
weak var view: ViewProtocol? // I choose this side of retain cycle to be weak, because `ViewController` is retained in UIWindow
}
I usually dont use SwinjectStoryboard, but if I were to, I would probably do it like this:
defaultContainer.registerForStoryboard(ViewController.self) { resolver, controller in
let presetner = resolver.resolve(Presenter.self)!
controller.presenter = presenter
presenter.view = controller
}
defaultContainer.register(Presenter.self) { _ in Presenter() }
I hope this helps 馃槃
There are defined types in the example above. What about I don't want to define class type but only 'interface'. The main idea of DI to resolve dependencies at run time
class LoginViewController: UIViewController, LoginViewInput {
var output: LoginViewOutput?
override func viewDidLoad() {
super.viewDidLoad()
output?.didTriggerViewDidLoad();
}
func say(message: String?) {
print(message)
}
}
class LoginPresenter: LoginViewOutput {
weak var view: LoginViewInput?
var presenter: LoginInteractorInput?
func didTriggerViewDidLoad() {
print("Did trigger View Did Load")
view?.say(message: "Hello")
}
}
@alynmuntean I will close this - if you have more questions, feel free to reopen this issue
@igorkotkovets I will respond to your question in SwinjectStoryboard #27, as it contains more info about the problem you are facing.
@jakubvano, sorry for my late response, the solution you provided works very well. Thank you! :)
Most helpful comment
Unfortunatelly,
SwinjectStoryboarddoes not support circular dependencies - as stated here you cannot directly callresolvefor view controllers initialised from storyboard - thus with your current setupresolver.resolve(AViewController.self)!will fail.Also, with your current setup there will be retain cycle between
BandAViewController- at least one of the references should be weak.When I need circular dependency with
UIViewControllerI typically use this setup:I usually dont use SwinjectStoryboard, but if I were to, I would probably do it like this:
I hope this helps 馃槃