| name | dependency-injection |
| description | Creates Features for dependency injection. Use when creating features, exposing public entry points, or wiring up dependencies. |
Skill: Dependency Injection
Guide for creating dependency injection with Composition Root pattern.
References
Architecture Overview
ChallengeApp
│
└── AppContainer (Composition Root)
│
├── httpClient: HTTPClientContract
├── tracker: TrackerContract
├── imageLoader: ImageLoaderContract → SwiftUI Environment
│
└── features: [Feature]
├── CharacterFeature (navigation + deep links)
│ └── CharacterContainer (DI composition)
│ ├── repository
│ ├── makeCharacterListView()
│ └── makeCharacterDetailView()
│
└── HomeFeature (navigation)
└── HomeContainer (DI composition)
└── makeHomeView()
Key Concepts
- AppContainer: Composition Root — creates shared dependencies (HTTPClient, Tracker) and all features
- {Feature}Container: Handles dependency composition (repositories, factories)
- {Feature}Feature: Handles navigation and deep links, delegates DI to Container
- Container factory methods create both ViewModel and View — callers receive a ready-to-use
some View
- Navigation is handled by App using
NavigationCoordinator
File Structure
App/
├── Sources/
│ └── {AppName}App.swift
AppKit/
├── Sources/
│ ├── AppContainer.swift
│ ├── Presentation/
│ │ ├── Navigation/
│ │ │ └── AppNavigationRedirect.swift
│ │ └── Views/
│ │ ├── NavigationContainerView.swift
│ │ ├── RootContainerView.swift
│ │ └── ModalContainerView.swift
Features/{Feature}/
├── Sources/
│ ├── {Feature}Feature.swift
│ ├── {Feature}Container.swift
│ ├── Navigation/
│ │ ├── {Feature}IncomingNavigation.swift
│ │ ├── {Feature}OutgoingNavigation.swift
│ │ └── {Feature}DeepLinkHandler.swift
│ └── Presentation/
│ └── {Screen}/
│ ├── Navigator/
│ ├── Tracker/
│ ├── Views/
│ └── ViewModels/
└── Tests/
└── Feature/
└── {Feature}FeatureTests.swift
Dependency Patterns
| Type | Pattern | Reason |
|---|
| HTTPClient | Required init parameter | Injected by AppContainer |
| Tracker | Required init parameter | Injected by AppContainer |
| ImageLoader | SwiftUI Environment | Injected by RootContainerView from AppContainer |
| Container | Created in Feature init | Owns dependency composition |
| DataSource | Local variable in Container init | Only needed to build repositories |
| Repository | Stored property in Container (let) | Built in init, used by factory methods |
| Navigator | Created inline inside Container factory method | New instance per View |
| Screen Tracker | Created inline inside Container factory method | New instance per View |
| ViewModel | Created inline inside Container factory method | New instance per View |
| View | Container factory method (make{Name}View) | Wraps ViewModel; returned as some View |
| UseCase | Created inline | Stateless |
Visibility Summary
| Component | Visibility | Reason |
|---|
| Contract (Protocol) | public | API for consumers, enables DI |
| {Feature}Feature | public | Entry point struct |
| {Feature}Container | internal | Created by Feature within same module |
| Feature.makeMainView() | public | Creates the feature's default entry point |
| Feature.resolve() | public | Returns view for navigation or nil |
| AppContainer.init | public | Only public member, created by ChallengeApp |
| AppContainer methods | internal/private | resolveView, handle, makeRootView are internal; rest private |
Container factory methods (make{Name}View) | internal | Called by Feature; return some View |
| {Feature}IncomingNavigation | public | Used by AppNavigationRedirect |
| {Feature}OutgoingNavigation | public | Used by AppNavigationRedirect |
| {Feature}DeepLinkHandler | internal | Accessed via Feature.deepLinkHandler |
| Navigator / Tracker / Views | internal | Internal to feature |
Checklist