0Pricing
Swift Academy · Lezione

Collegare i livelli senza un framework DI

Comporre gli oggetti nel punto di ingresso dell’app usando il pattern Composition Root.

Collegare i livelli senza un framework DI è una lezione Swift Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Swift Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Swift Academy include 4 lezioni in totale.

Composition Root

Il Composition Root è l'unico punto in cui tutti gli oggetti vengono istanziati e collegati tra loro. In un'app SwiftUI, in genere corrisponde a @main.

@main
struct MyApp: App {
  // All wiring happens here
  private let container = AppContainer()
  var body: some Scene {
    WindowGroup { container.makeRootView() }
  }
}

Pattern AppContainer

Una struct/classe AppContainer costruisce il grafo degli oggetti, nascondendo la complessità dei collegamenti alla struct App.

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) }
}

Proprietà lazy per l'ordine di costruzione

Usare proprietà lazy per assicurarsi che le dipendenze vengano costruite nell'ordine corretto senza doverlo gestire manualmente.

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)
}

Metodi factory

Aggiungere metodi factory al container per creare oggetti a livello di vista con dipendenze specifiche per ogni schermata.

extension AppContainer {
  func makeOrderFlow() -> OrderFlowView {
    let repo = RemoteOrderRepository(api: api)
    let useCase = PlaceOrderUseCase(repo: repo)
    let vm = OrderViewModel(useCase: useCase)
    return OrderFlowView(viewModel: vm)
  }
}

Environment Values per l'injection

In SwiftUI, usare EnvironmentKey personalizzati per inserire dipendenze in profondità nell'albero delle viste senza doverle passare attraverso ogni livello.

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 }
  }
}

Utilizzo dell'Environment Key

Inserire la dipendenza con .environment(\.fetchUser, container.fetchUser) e leggerla nelle viste con @Environment(\.fetchUser).

ContentView()
  .environment(\.fetchUser, container.fetchUser)

// In a deep view:
@Environment(\.fetchUser) private var fetchUser

Container con ambito

Creare container figli per gli ambiti delle funzionalità, ereditando le dipendenze condivise e gestendo quelle specifiche della funzionalità.

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
  }
}

Test del Composition Root

Testare i metodi factory del container verificando che gli oggetti restituiti abbiano il tipo e la configurazione corretti.

func testContainerBuildsProfileView() {
  let container = AppContainer(db: InMemoryDatabase())
  let view = container.makeRootView()
  XCTAssertTrue(type(of: view) == ProfileView.self)
}

Come evitare le dipendenze circolari

Se A dipende da B e B dipende da A, introdurre un mediator o riorganizzare le responsabilità per interrompere il ciclo.

// Circular:
// UserService → NotificationService → UserService
// Fix: UserService → NotificationInput (protocol) ← NotificationService

Quando ricorrere a un framework DI

Il collegamento manuale si adatta bene alle app di medie dimensioni. Valutare framework come Needle e Swinject solo quando il container diventa troppo grande da gestire.

// Manual: fine for <20 top-level dependencies
// Framework: helps with large teams, 50+ services, code-generation for factories

Esempio riepilogativo

Esempio completo di collegamento in una piccola app: il container costruisce tutte le dipendenze e una factory produce la vista radice.

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))
  }
}

Verifica rapida

Che cos'è il Composition Root in un'app Swift?

Riepilogo della lezione

Configurare l'app in un Composition Root (in genere @main). Usare un AppContainer con proprietà lazy per garantire il corretto ordine di costruzione. Aggiungere metodi factory per i grafi specifici di ogni schermata. Inserire le dipendenze profonde tramite EnvironmentKey personalizzati. Interrompere le dipendenze circolari con protocolli mediator.

Domande Frequenti

La lezione «Collegare i livelli senza un framework DI» è gratuita?

Sì — il testo completo di «Collegare i livelli senza un framework DI» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Swift Academy, passa a CoddyKit PRO. Il corso Swift Academy include 4 lezioni in totale.

Cosa imparerò in «Collegare i livelli senza un framework DI»?

Comporre gli oggetti nel punto di ingresso dell’app usando il pattern Composition Root. Eserciti Swift Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Swift Academy?

Non è richiesta alcuna esperienza precedente. Swift Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.

Quanto tempo richiede la lezione «Collegare i livelli senza un framework DI»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Swift Academy?

Sì. Ogni lezione Swift Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Livelli: dominio, dati e presentazione
  2. Pattern Use Case e Repository
  3. Inversione delle dipendenze con astrazioni basate su protocolli
  4. Collegare i livelli senza un framework DI
← Torna a Swift Academy