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

Why keep container in AppDelegate? #416

Closed
vermont42 opened this issue Jun 15, 2019 · 4 comments

Comments

Projects
None yet
4 participants
@vermont42
Copy link

commented Jun 15, 2019

I am preparing a conference talk that compares various approaches to dependency injection, including Swinject. The demonstration app for the talk uses programmatic layout. I am curious why your readme recommends making the container a computed property in AppDelegate.

I can see two problems with this approach as opposed to, say, making the container's contents globally accessible (the approach I used here) or injecting the container into the top-level view controller. First, keeping the container in AppDelegate violates separation of concerns. That is, the job of AppDelegate is responding to app-lifecycle events, not to hold onto a dependency container. Second, if any object other than AppDelegate needs to use the container, that object must first get a reference to AppDelegate, adding visual clutter.

I might be missing something. If there is a compelling reason for AppDelegate to own the container, I'd like to share that with the audience of the conference talk.

@jakubvano

This comment has been minimized.

Copy link
Member

commented Jun 17, 2019

Example in the readme is meant to be only illustrational, mainly highlighting differences if usage with / without the SwinjectStoryboard. There is no reason to keep container in the AppDelegate - in reasonably large apps I would expect it to be globally(ish) accessible, integrated in some way to the overall architecture.

@drekka

This comment has been minimized.

Copy link

commented Jun 18, 2019

I don't know if people think this is a good idea or not :-), but as the Swinject container needs to effectively be a global Singleton accessible almost immediately, I've been declaring it as a global variable and often used two similar to this (which I often declare in their own file along with the class registrations)

/// In a service/backend/business logic framework
public let servicesContainer = Container()

/// ... and in the UI
public let uiContainer = Container(parent: servicesContainer)

I know it's frowned upon to declare global variables like this and generally I'd agree, but this one of the very few times I think they are the best solution. You can place a property on the app delegate, or the app, or in some other location, or you can use class variables as another approach. But regardless of what you do, you still have to treat the containers as singletons.

@SergeRykovski

This comment has been minimized.

Copy link

commented Jul 5, 2019

The idea behind inversion of control is that each class is only aware of its dependencies but should not know where or how to get them. The responsibility of connecting things together can be moved to a so called composition root which makes it a natural place to store a reference to container. It should be as close as possible to application launch point and for iOS arguably it should be somewhere in the AppDelegate.
Also having a wrapper for DI container (any, not specifically Swinject) may be considered and anti-pattern.

You can read more about composition root pattern here and about wrapping container here.

@vermont42

This comment has been minimized.

Copy link
Author

commented Jul 6, 2019

Thanks, @jakubvano, @drekka, and @SergeRykovski. I plan to mention your helpful replies!

@vermont42 vermont42 closed this Jul 7, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.