square / Cleanse

Lightweight Swift Dependency Injection Framework
Other
1.78k stars 90 forks source link

Usage with storyboards. #104

Closed mahin8514 closed 5 years ago

mahin8514 commented 5 years ago

How can I use storyboard with cleanse?

sebastianv1 commented 5 years ago

@mahin8514 This is usually done via Property Injection alongside the Storyboard instantiateViewController(withIdentifier:) function.

So if you have ViewControllerA you can create a property injector instance:

binder
    .bindPropertyInjectionOf(ViewControllerA.self)
    .to { (target: ViewControllerA, dependencyA: DepA, dependencyB: DepB) in
            target.depA = dependencyA
            target.depB = dependencyB
    }

And then wherever you want to present ViewControllerA (say in RootViewController), you would include a PropertyInjector<ViewControllerA> instance as a dependency of RootViewController (Cleanse will construct this object for you through the bindPropertyInjectionOf binding) and then call instantiateViewController(withIdentifier:).

class RootViewController
    let injector: PropertyInjector<ViewControllerA>
    init(injector: PropertyInjector<ViewControllerA>) {
        self.injector = injector
    }
    ...
    func presentViewControllerA() {
        let vc_a = storyboard.instantiateViewController(withIdentifier "VC-A-Identifier")
        injector.injectProperties(into: vc_a)
    }
}
baillyjamy commented 3 years ago

Hello, I'm trying to instantiate my ViewControllers with my storyboard and inject my deps with bindPropertyInjectionOf based on your sample but with a router pattern.

So for exemple I have :

RouterA in ViewControllerA (is RootViewController) RouterB in ViewControllerB ViewControllerC

Each router instantiate next ViewController. My code looks something like this in RouterA :

class RouterA {

    let storyboard = UIStoryboard(name: "Main", bundle: nil)

    enum Route: String {
        case routeB
        ....
    }

    let injector: PropertyInjector<ViewControllerB>

    init(injector: PropertyInjector<ViewControllerB>) {
        self.injector = injector

    }

    ....

    func route(to routeIdentifier: String, from context: UIViewController, parameters: Any? = nil) {
        guard let route = Route(rawValue: routeIdentifier) else {
            return
        }
        switch route {
        case .routeB:
            if let vc = storyboard.instantiateViewController(withIdentifier: "ViewControllerB") as? ViewControllerB {
                homeViewControllerInjector.injectProperties(into: vc)
                ....
            }
        }
        ....
    }
}

But I don't understand how to send the PropertyInjector of my future ViewController into my routes. Specially in my first router in my RootViewController

sebastianv1 commented 3 years ago

@baillyjamy I don't quite follow exactly what you're trying to accomplish. If you need another property injector for say ViewControllerC, you should be able to just create another PropertyInjector binding for ViewControllerC and inject that alongside your PropertyInjector<ViewControllerB> (init(injectorB: PropertyInjector<ViewControllerB>, injectorC: PropertyInjector<ViewControllerC>) { ... })