Koppla ihop lager utan ett DI-ramverk
Komponera objekt vid appens startpunkt med mönstret Composition Root.
Koppla ihop lager utan ett DI-ramverk är en gratis lektion i Swift Academy på CoddyKit. Detta är lektion 4 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Swift Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Swift Academy innehåller totalt 4 lektioner.
Composition Root
Composition Root är den enda plats där alla objekt instansieras och kopplas samman. I en SwiftUI-app är det vanligtvis @main.
@main
struct MyApp: App {
// All wiring happens here
private let container = AppContainer()
var body: some Scene {
WindowGroup { container.makeRootView() }
}
}AppContainer-mönstret
En AppContainer-struct eller -class bygger objektgrafen och döljer komplexiteten i kopplingarna från App-strukturen.
final class AppContainer {
let db = SQLiteDatabase()
lazy var userRepo: UserRepository = RemoteUserRepository(db: db)
lazy var fetchUser = FetchUserUseCase(repo: userRepo)
lazy var profileVM = ProfileViewModel(useCase: fetchUser)
func makeRootView() -> some View { ProfileView(viewModel: profileVM) }
}Lazy-egenskaper för ordningsföljd
Använd egenskaper med lazy för att säkerställa att beroenden byggs i rätt ordning utan manuell ordning.
final class Container {
lazy var network: NetworkClient = URLSessionClient()
lazy var api: APIService = APIService(client: network) // created after network
lazy var repo: ItemRepository = RemoteItemRepository(api: api)
}Factory-metoder
Lägg till factory-metoder i containern för att skapa objekt på vynivå med skärmspecifika beroenden.
extension AppContainer {
func makeOrderFlow() -> OrderFlowView {
let repo = RemoteOrderRepository(api: api)
let useCase = PlaceOrderUseCase(repo: repo)
let vm = OrderViewModel(useCase: useCase)
return OrderFlowView(viewModel: vm)
}
}Miljövärden för injektion
I SwiftUI används anpassade EnvironmentKey-nycklar för att injicera beroenden djupt i vyträdet utan att skicka egenskaper genom alla vyer.
private struct FetchUserKey: EnvironmentKey {
static let defaultValue: FetchingUser = FetchUserUseCase(repo: NullUserRepo())
}
extension EnvironmentValues {
var fetchUser: FetchingUser {
get { self[FetchUserKey.self] } set { self[FetchUserKey.self] = newValue }
}
}Använda miljönyckeln
Injicera via .environment(\.fetchUser, container.fetchUser) och läs av värdet med @Environment(\.fetchUser) i vyerna.
ContentView()
.environment(\.fetchUser, container.fetchUser)
// In a deep view:
@Environment(\.fetchUser) private var fetchUserOmfattningsbegränsade containrar
Skapa underordnade containrar för funktionsomfattningar. De ärver gemensamma beroenden men äger de funktionsspecifika beroendena.
final class CheckoutContainer {
let cart: CartRepository
let payment: PaymentService
lazy var placeOrder = PlaceOrderUseCase(cart: cart, payment: payment)
init(parent: AppContainer) {
cart = parent.cartRepo
payment = parent.paymentService
}
}Testa Composition Root
Testa containerns factory-metoder genom att verifiera att de returnerade objekten har rätt typ och konfiguration.
func testContainerBuildsProfileView() {
let container = AppContainer(db: InMemoryDatabase())
let view = container.makeRootView()
XCTAssertTrue(type(of: view) == ProfileView.self)
}Undvik cirkulära beroenden
Om A är beroende av B och B är beroende av A kan en mediator införas eller ansvarsområdena struktureras om för att bryta cykeln.
// Circular:
// UserService → NotificationService → UserService
// Fix: UserService → NotificationInput (protocol) ← NotificationServiceNär bör ett DI-ramverk användas
Manuell koppling fungerar bra i medelstora appar. Överväg ramverk (Needle, Swinject) först när containern blir för stor för att underhålla.
// Manual: fine for <20 top-level dependencies
// Framework: helps with large teams, 50+ services, code-generation for factoriesExempel på sammanfattning
Ett komplett exempel på koppling i en liten app: containern bygger alla beroenden och en factory skapar rotvyn.
final class AppContainer {
private let db = CoreDataStack.shared
lazy var userRepo: UserRepository = LocalUserRepository(db: db)
lazy var fetchUser = FetchUserUseCase(repo: userRepo)
func makeContentView() -> ContentView {
ContentView(viewModel: ProfileViewModel(useCase: fetchUser))
}
}Snabbkontroll
Vad är Composition Root i en Swift-app?
Lektionssammanfattning
Koppla samman appen i en Composition Root (vanligtvis @main). Använd en AppContainer med egenskaper som använder lazy för rätt byggordning. Lägg till factory-metoder för beroendegrafer per skärm. Injicera djupa beroenden via anpassade EnvironmentKey-nycklar. Bryt cirkulära beroenden med mediatorprotokoll.
Lär dig Swift med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 122
- Lektioner
- 409
Vanliga frågor
Är lektionen ”Koppla ihop lager utan ett DI-ramverk” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Swift Academy, inklusive ”Koppla ihop lager utan ett DI-ramverk”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Swift Academy innehåller totalt 4 lektioner.
Vad lär jag mig i ”Koppla ihop lager utan ett DI-ramverk”?
Komponera objekt vid appens startpunkt med mönstret Composition Root. Ni övar på Swift Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Swift Academy?
Du behöver inga förkunskaper. Utbildningen i Swift Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.
Hur lång tid tar lektionen ”Koppla ihop lager utan ett DI-ramverk”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Swift Academy-lektionen?
Ja. Varje Swift Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Lager: domän, data och presentation
- Use case- och repository-mönster
- Beroendeinversion med protokollabstraktioner
- Koppla ihop lager utan ett DI-ramverk