Swift Academy · Lektion

Koppla ihop lager utan ett DI-ramverk

Komponera objekt vid appens startpunkt med mönstret Composition Root.

Lektion 4 av 413 steg

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 fetchUser

Omfattningsbegrä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) ← NotificationService

Nä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 factories

Exempel 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.

Gratis att börja

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

  1. Lager: domän, data och presentation
  2. Use case- och repository-mönster
  3. Beroendeinversion med protokollabstraktioner
  4. Koppla ihop lager utan ett DI-ramverk
← Tillbaka till Swift Academy