Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to solve circular dependency? #396

Open
Ewg777 opened this issue Sep 22, 2021 · 6 comments
Open

How to solve circular dependency? #396

Ewg777 opened this issue Sep 22, 2021 · 6 comments

Comments

@Ewg777
Copy link

Ewg777 commented Sep 22, 2021

Here is an example of a component


class ABCComponent: Component<EmptyDependency>{


    var a: AProtocol {
        A(b)
    }

    var b: BProtocol {
        B(c)
    }

    var c: CProtocol {
        C(a)
    }


Now needle stucks in runtime try to resolve it. Is there a way to fix it?
Thanks

@Ewg777
Copy link
Author

Ewg777 commented Sep 23, 2021

Full example


@UIApplicationMain
final class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        registerProviderFactories()
        let rootComponent = RootComponent()
        let aaa = rootComponent.aaa
        print(aaa)
...

protocol AProtocol {
}

protocol BProtocol {
}

protocol CProtocol {
}

class A: AProtocol {
    init(b: BProtocol) {}
}

class B: BProtocol {
    init(c: CProtocol) {}
}

class C: CProtocol {
    init(a: AProtocol) {}
}

class ABCComponent: Component<EmptyDependency> {

    var a: AProtocol {
        A(b: b)
    }

    var b: BProtocol {
        B(c: c)
    }

    var c: CProtocol {
        C(a: a)
    }
}


final class RootComponent: BootstrapComponent {

    var abc: ABCComponent {
        ABCComponent(parent: self)
    }

    var aaa: AProtocol {
        abc.a
    }
}

@Ewg777
Copy link
Author

Ewg777 commented Sep 23, 2021

Screenshot 2021-09-23 at 08 33 05

@Ewg777
Copy link
Author

Ewg777 commented Sep 23, 2021

@rudro @neakor could you help please?

@rudro
Copy link
Collaborator

rudro commented Oct 5, 2021

Thanks for the full example, but I don't think this has anything to do with Needle. Consider this code:

class ABCComponent {

    var a: AProtocol {
        A(b: b)
    }

    var b: BProtocol {
        B(c: c)
    }

    var c: CProtocol {
        C(a: a)
    }

     init() {}
}

let c = ABCComponent()
print(c.a)

Even if there's no Needle, this print statement will run into the same issue.

@Ewg777
Copy link
Author

Ewg777 commented Oct 6, 2021

@rudro thanks for your feedback!
Let me give you one more example. Here is more realistic example. Please let me know if it's possible to resolve with Needle.

protocol ViewControllerProtocol: AnyObject {
}

protocol PresenterProtocol {
}

protocol RouterProtocol {
}

class AViewController: ViewControllerProtocol {
    var presenter: PresenterProtocol!
}

class Presenter: PresenterProtocol {
    var router: RouterProtocol!
}

class Router: RouterProtocol {
    weak var controller: ViewControllerProtocol?

    init(controller: ViewControllerProtocol) {
        self.controller = controller
    }
}

class ABCComponent {

    var aViewController: ViewControllerProtocol!
}

@micHar
Copy link

micHar commented Dec 2, 2021

Legit question. It's of course not possible to resolve circular dependency statically (by the very nature of the problem), but usually these use cases can be dealt with the usage of lazy injection, i.e. one of the dependencies in the circle is not resolved statically, but only injected upon usage. Needle seems to be inspired by dagger somewhat, so this link might help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants