Effects und Dependencies
Behandeln Sie Seiteneffekte und injizieren Sie Abhängigkeiten.
Effects und Dependencies ist eine kostenlose Swift Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Swift Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Swift Academy-Kurs umfasst insgesamt 4 Lektionen.
Warum es Effects gibt
Reducer müssen rein bleiben: Aus einem State und einer Action verändern sie ausschließlich den State. Echte Apps benötigen jedoch Seiteneffekte wie Netzwerkanfragen und Timer. TCA modelliert diese als Effects, die der Reducer zurückgibt. So bleibt die Mutation rein, während die asynchrone Arbeit getrennt ausgeführt wird.
Diese Trennung macht Features testbar.
import ComposableArchitecture
// Reducer stays pure; side effects are values it returns.
// Returning .none means no further work..none zurückgeben
Wenn eine Action nur den State ändert und keine anschließende Arbeit benötigt, gibt der Reducer .none zurück. Dies ist der häufigste Effect und signalisiert, dass keine asynchrone Arbeit ausgeführt werden muss.
Sie haben dies bereits gesehen. Jeder Zweig verwendet dies als Standardrückgabe.
import ComposableArchitecture
Reduce { state, action in
switch action {
case .incrementTapped:
state.count += 1
return .none
}
}Effect.run für asynchrone Arbeit
Um asynchrone Arbeit auszuführen, geben Sie .run zurück. Die Closure erhält einen send-Handle, mit dem Sie Ergebnisse als neue Actions in das System zurückgeben.
Hier lädt eine Fetch-Action Daten und sendet nach Abschluss eine 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
}
}Ergebnisse als Actions zurückgeben
Ein Effect kann den State nicht direkt verändern, sondern sendet stattdessen Actions über send. Der Reducer verarbeitet diese Actions anschließend und aktualisiert den State. So bleibt jede Mutation innerhalb des Reducers.
Eine Netzwerkantwort wird dadurch zu einer Response-Action, die der Reducer speichert.
import ComposableArchitecture
.run { send in
let result = try await fetch()
await send(.dataLoaded(result))
}
// .dataLoaded is then handled by the reducer to set state.Fehler in Effects behandeln
Asynchrone Arbeit kann Fehler werfen. Sie können Fehler innerhalb des Effects abfangen und eine Failure-Action senden, sodass der Reducer sauber in einen Fehlerzustand wechseln kann.
Die optionale catch-Closure von .run erhält den geworfenen Fehler.
import ComposableArchitecture
.run { send in
let value = try await loadNumber()
await send(.responseReceived(value))
} catch: { error, send in
await send(.loadFailed)
}Warum Dependencies wichtig sind
Wenn ein Reducer direkt einen Netzwerk-Client aufruft oder das Datum ausliest, wird er schwer testbar und kontrollierbar. TCA löst dies mit Dependencies: injizierbaren Diensten, auf die Ihr Reducer über @Dependency zugreift.
In Tests ersetzen Sie sie durch vorhersehbare Fakes.
import ComposableArchitecture
// Instead of calling APIClient.shared directly,
// inject it as a dependency so tests can replace it.Der @Dependency-Property-Wrapper
Innerhalb eines Reducers deklarieren Sie eine Dependency mit @Dependency und benennen sie über ihren Key Path in den Dependency-Werten. Die Bibliothek stellt integrierte Dependencies bereit, etwa eine Uhr und einen UUID-Generator.
Hier bindet der Reducer die kontinuierliche Uhr ein.
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 }
}
}Eine Dependency in einem Effect verwenden
Nach der Deklaration verwenden Sie die Dependency innerhalb von .run. Da die Uhr injiziert wird, können Tests eine Testuhr bereitstellen, die die Zeit bei Bedarf voranschreiten lässt.
Hier wird der Timer mithilfe der injizierten Uhr jede Sekunde ausgelöst.
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
}
}
}Eine eigene Dependency definieren
Sie registrieren eigene Dependencies, indem Sie einen Wert DependencyKey entsprechen lassen und einen liveValue bereitstellen. Anschließend fügen Sie DependencyValues eine berechnete Eigenschaft hinzu, damit ein Key Path verfügbar ist.
Hier wird ein API-Client zu einer vollwertigen Dependency.
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 }
}
}Die eigene Dependency injizieren
Mit dem eingerichteten Key Path deklariert der Reducer den Client mit @Dependency(\.numberClient) und ruft ihn innerhalb von Effects auf. In der Produktion wird der Live-Wert verwendet, während Tests ihn überschreiben.
Hier lädt eine Reload-Action Daten über den injizierten 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
}
}
}
}Effekte abbrechen
Lang laufende Effekte wie Timer sollten abbrechbar sein. Sie versehen einen Effekt mit einer cancellable-ID und brechen ihn später aus einer anderen Aktion mit .cancel ab.
Hier kann der Timer bei Bedarf gestoppt werden.
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)Kurztest: Effekte und Ergebnisse
Rufen Sie sich ins Gedächtnis, wie ein Effekt sein Ergebnis an den Reducer zurückmeldet.
Zusammenfassung: Effekte und Abhängigkeiten
Sie haben gelernt, wie TCA Seiteneffekte und Dependency Injection handhabt:
- Reducer bleiben rein und liefern
Effect-Werte;.nonebedeutet, dass keine Arbeit anfällt. .runführt asynchrone Arbeit aus und leitet Ergebnisse überawait send(.action)zurück.- Fehler werden in der
catch-Closure des Effekts behandelt. @Dependencyinjiziert Services wie die Uhr oder eigene Clients, die überDependencyKeyundDependencyValuesdeklariert werden.- Lang laufende Effekte können anhand einer ID als
cancellableausgeführt werden.
Als Nächstes setzen Sie Features zusammen und testen sie umfassend.
import ComposableArchitecture
// Recap: pure reducer + Effect.run for async work
// + @Dependency for testable, injectable services.Lerne Swift mit einem KI-Tutor — kostenlos
Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.
- Kurse
- 122
- Lektionen
- 409
Häufig gestellte Fragen
Ist die Lektion „Effects und Dependencies“ kostenlos?
Ja — der vollständige Text von „Effects und Dependencies“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Swift Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Swift Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Effects und Dependencies“?
Behandeln Sie Seiteneffekte und injizieren Sie Abhängigkeiten. Du übst Swift Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Swift Academy zu starten?
Keine Vorkenntnisse erforderlich. Swift Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.
Wie lange dauert die Lektion „Effects und Dependencies“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Swift Academy-Lektion Code schreiben und ausführen?
Ja. Jede Swift Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- State, Action und Reducer
- Der Store und die SwiftUI-Integration
- Effects und Dependencies
- Features kombinieren und testen