Effects en dependencies
Verwerk side effects en injecteer dependencies.
Effects en dependencies is een gratis Swift Academy-les op CoddyKit. Dit is les 3 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Swift Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Swift Academy bevat in totaal 4 lessen.
Waarom Effects bestaan
Reducers moeten puur blijven: gegeven een state en een action wijzigen ze alleen state. Maar echte apps hebben bijwerkingen nodig, zoals netwerkaanvragen en timers. TCA modelleert deze als Effects die de reducer retourneert, zodat de mutatie puur blijft terwijl het asynchrone werk apart wordt uitgevoerd.
Dankzij deze scheiding zijn features goed te testen.
import ComposableArchitecture
// Reducer stays pure; side effects are values it returns.
// Returning .none means no further work..none retourneren
Wanneer een action alleen state wijzigt en geen vervolgwerk nodig heeft, retourneert de reducer .none. Dit is het meest voorkomende effect en geeft aan dat er niets asynchroon hoeft te gebeuren.
Je hebt dit al gezien; het is de basis waarop elke tak terugvalt.
import ComposableArchitecture
Reduce { state, action in
switch action {
case .incrementTapped:
state.count += 1
return .none
}
}Effect.run voor asynchroon werk
Om asynchroon werk uit te voeren, retourneer je .run. De closure ontvangt een send-handvat waarmee je resultaten als nieuwe actions terug het systeem in stuurt.
Hier laadt een fetch-action gegevens en stuurt deze na afloop een response-action.
import ComposableArchitecture
Reduce { state, action in
switch action {
case .reloadTapped:
return .run { send in
let value = try await loadNumber()
await send(.responseReceived(value))
}
case let .responseReceived(value):
state.count = value
return .none
}
}Resultaten als Actions terugsturen
Een effect kan state niet rechtstreeks wijzigen; in plaats daarvan stuurt het actions via send. De reducer handelt die actions vervolgens af en werkt state bij. Dankzij deze lus vinden alle mutaties binnen de reducer plaats.
Zo wordt een netwerkreactie een response-action die de reducer opslaat.
import ComposableArchitecture
.run { send in
let result = try await fetch()
await send(.dataLoaded(result))
}
// .dataLoaded is then handled by the reducer to set state.Fouten in Effects afhandelen
Asynchroon werk kan fouten veroorzaken. Je kunt fouten in het effect opvangen en een failure-action sturen, zodat de reducer netjes naar een foutstatus kan gaan.
De optionele closure catch op .run ontvangt de veroorzaakte fout.
import ComposableArchitecture
.run { send in
let value = try await loadNumber()
await send(.responseReceived(value))
} catch: { error, send in
await send(.loadFailed)
}Waarom afhankelijkheden belangrijk zijn
Als een reducer een netwerkclient aanroept of de datum rechtstreeks leest, wordt deze moeilijk te testen en te beheersen. TCA lost dit op met afhankelijkheden: injecteerbare diensten die je reducer benadert via @Dependency.
Bij het testen vervang je ze door voorspelbare testdubbels.
import ComposableArchitecture
// Instead of calling APIClient.shared directly,
// inject it as a dependency so tests can replace it.De property-wrapper @Dependency
Binnen een reducer declareer je een afhankelijkheid met @Dependency en benoem je deze via het key path in de afhankelijkheidswaarden. De bibliotheek levert ingebouwde afhankelijkheden, zoals een klok en een UUID-generator.
Hier haalt de reducer de doorlopende klok op.
import ComposableArchitecture
@Reducer
struct TimerFeature {
@ObservableState
struct State: Equatable { var seconds = 0 }
enum Action { case start, tick }
@Dependency(\.continuousClock) var clock
var body: some ReducerOf<Self> {
Reduce { state, action in .none }
}
}Een afhankelijkheid in een effect gebruiken
Zodra de afhankelijkheid is gedeclareerd, gebruik je deze binnen .run. Omdat de klok is geïnjecteerd, kunnen testklokken tijdens het testen op aanvraag tijd vooruitzetten.
Hier tikt de timer elke seconde met behulp van de geïnjecteerde klok.
import ComposableArchitecture
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .start:
return .run { send in
for await _ in self.clock.timer(interval: .seconds(1)) {
await send(.tick)
}
}
case .tick:
state.seconds += 1
return .none
}
}
}Je eigen afhankelijkheid definiëren
Je registreert aangepaste afhankelijkheden door een waarde te laten voldoen aan DependencyKey en een liveValue te leveren. Vervolgens voeg je een berekende eigenschap toe aan DependencyValues, zodat deze een key path krijgt.
Hier wordt een API-client een volwaardige afhankelijkheid.
import ComposableArchitecture
struct NumberClient {
var fetch: () async throws -> Int
}
extension NumberClient: DependencyKey {
static let liveValue = NumberClient {
try await loadNumber()
}
}
extension DependencyValues {
var numberClient: NumberClient {
get { self[NumberClient.self] }
set { self[NumberClient.self] = newValue }
}
}De aangepaste afhankelijkheid injecteren
Met het key path op zijn plaats declareert de reducer de client met @Dependency(\.numberClient) en roept deze aan binnen effecten. In productie wordt de live value gebruikt; bij het testen overschrijf je deze.
Hier haalt een herlaadactie gegevens op via de geïnjecteerde client.
import ComposableArchitecture
@Reducer
struct NumberFeature {
@ObservableState
struct State: Equatable { var value = 0 }
enum Action { case reload, response(Int) }
@Dependency(\.numberClient) var numberClient
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .reload:
return .run { send in
let n = try await numberClient.fetch()
await send(.response(n))
}
case let .response(n):
state.value = n
return .none
}
}
}
}Effecten annuleren
Langlopende effecten, zoals timers, moeten kunnen worden geannuleerd. Je voorziet een effect van een cancellable-id en annuleert het later vanuit een andere actie met .cancel.
Hier kun je de timer op verzoek stoppen.
import ComposableArchitecture
enum CancelID { case timer }
// Start a cancellable effect:
.run { send in /* ... */ }
.cancellable(id: CancelID.timer)
// Stop it from another action:
.cancel(id: CancelID.timer)Snelle controle: effecten en resultaten
Haal je voor de geest hoe een effect zijn resultaat terugstuurt naar de reducer.
Samenvatting: effecten en afhankelijkheden
Je hebt geleerd hoe TCA neveneffecten en injectie afhandelt:
- Reducers blijven puur en retourneren
Effect-waarden;.nonebetekent dat er niets wordt uitgevoerd. .runvoert asynchroon werk uit en stuurt resultaten terug viaawait send(.action).- Fouten worden afgehandeld met de
catch-closure van het effect. @Dependencyinjecteert diensten zoals de klok of je eigen clients, die worden gedeclareerd viaDependencyKeyenDependencyValues.- Langlopende effecten kunnen op basis van een id
cancellableworden gemaakt.
Vervolgens combineer je onderdelen en test je ze volledig.
import ComposableArchitecture
// Recap: pure reducer + Effect.run for async work
// + @Dependency for testable, injectable services.Leer Swift met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 122
- Lessen
- 409
Veelgestelde vragen
Is de les “Effects en dependencies” gratis?
Ja — je kunt hier op het web alle 3 lessen van het leerpad Swift Academy, waaronder “Effects en dependencies”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus Swift Academy bevat in totaal 4 lessen.
Wat leer ik in “Effects en dependencies”?
Verwerk side effects en injecteer dependencies. Je oefent met Swift Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Swift Academy te beginnen?
Ervaring vooraf is niet nodig. Swift Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 4.
Hoe lang duurt de les “Effects en dependencies”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Swift Academy?
Ja. Elke les over Swift Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- State, action en reducer
- De Store en SwiftUI-integratie
- Effects en dependencies
- Features samenstellen en testen