Swift Academy · Pelajaran

Efek dan Dependensi

Tangani efek samping dan injeksikan dependensi.

Pelajaran 3 dari 413 langkah

Efek dan Dependensi adalah pelajaran Swift Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Swift Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Swift Academy mencakup 4 pelajaran total.

Mengapa Efek Ada

Reducer harus tetap murni: dengan State dan Action tertentu, Reducer hanya mengubah keadaan. Namun, aplikasi nyata memerlukan efek samping seperti permintaan jaringan dan pewaktu. TCA memodelkannya sebagai efek yang dikembalikan Reducer, sehingga perubahan tetap murni sementara pekerjaan asinkron berjalan secara terpisah.

Pemisahan inilah yang membuat fitur dapat diuji.

import ComposableArchitecture

// Reducer stays pure; side effects are values it returns.
// Returning .none means no further work.

Mengembalikan .none

Jika sebuah tindakan hanya mengubah keadaan dan tidak memerlukan pekerjaan lanjutan, Reducer mengembalikan .none. Inilah efek yang paling umum dan menandakan bahwa tidak ada pekerjaan asinkron yang perlu dilakukan.

Anda sudah melihatnya; ini adalah dasar yang menjadi pilihan cadangan setiap cabang.

import ComposableArchitecture

Reduce { state, action in
    switch action {
    case .incrementTapped:
        state.count += 1
        return .none
    }
}

Effect.run untuk Pekerjaan Asinkron

Untuk melakukan pekerjaan asinkron, Anda mengembalikan .run. Fungsi penutupnya menerima penangan send yang Anda gunakan untuk memasukkan hasil kembali ke sistem sebagai tindakan baru.

Di sini, tindakan fetch memuat data dan mengirimkan tindakan respons setelah selesai.

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

Mengembalikan Hasil sebagai Action

Efek tidak dapat mengubah keadaan secara langsung; efek mengirimkan tindakan melalui send. Reducer kemudian menangani tindakan tersebut dan memperbarui keadaan. Perulangan ini memastikan setiap perubahan tetap berada di dalam Reducer.

Jadi, respons jaringan menjadi tindakan respons yang disimpan oleh Reducer.

import ComposableArchitecture

.run { send in
    let result = try await fetch()
    await send(.dataLoaded(result))
}
// .dataLoaded is then handled by the reducer to set state.

Menangani Galat dalam Efek

Pekerjaan asinkron dapat menghasilkan galat. Anda dapat menangkap galat di dalam efek dan mengirimkan tindakan kegagalan, sehingga Reducer dapat berpindah ke keadaan galat dengan rapi.

Fungsi penutup catch opsional pada .run menerima galat yang dilemparkan.

import ComposableArchitecture

.run { send in
    let value = try await loadNumber()
    await send(.responseReceived(value))
} catch: { error, send in
    await send(.loadFailed)
}

Mengapa Dependensi Penting

Jika Reducer memanggil klien jaringan atau membaca tanggal secara langsung, Reducer menjadi sulit diuji dan dikendalikan. TCA mengatasinya dengan dependensi: layanan yang dapat disuntikkan dan diakses Reducer melalui @Dependency.

Dalam pengujian, Anda menggantinya dengan tiruan yang hasilnya dapat diprediksi.

import ComposableArchitecture

// Instead of calling APIClient.shared directly,
// inject it as a dependency so tests can replace it.

Pembungkus Properti @Dependency

Di dalam Reducer, Anda mendeklarasikan dependensi dengan @Dependency dan menamainya berdasarkan jalur kuncinya dalam nilai dependensi. Pustaka menyediakan komponen bawaan seperti jam dan penghasil UUID.

Di sini, Reducer mengambil jam kontinu.

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

Menggunakan Dependensi dalam Efek

Setelah dideklarasikan, Anda menggunakan dependensi tersebut di dalam .run. Karena jam disuntikkan, pengujian dapat menyediakan jam pengujian yang memajukan waktu sesuai kebutuhan.

Di sini, timer berdetak setiap detik menggunakan jam yang disuntikkan.

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

Mendefinisikan Dependensi Sendiri

Anda mendaftarkan dependensi khusus dengan membuat suatu nilai memenuhi DependencyKey dan menyediakan liveValue. Kemudian, Anda menambahkan properti terhitung ke DependencyValues agar dependensi tersebut memiliki jalur kunci.

Di sini, klien API menjadi dependensi utama.

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

Menyuntikkan Dependensi Khusus

Setelah jalur kunci tersedia, Reducer mendeklarasikan klien dengan @Dependency(\.numberClient) dan memanggilnya di dalam efek. Produksi menggunakan nilai aktif; pengujian menggantinya.

Di sini, tindakan muat ulang mengambil data melalui klien yang disuntikkan.

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

Membatalkan Efek

Efek yang berjalan lama seperti pengatur waktu harus dapat dibatalkan. Anda menandai efek dengan ID cancellable dan membatalkannya nanti dari tindakan lain dengan .cancel.

Di sini, pengatur waktu dapat dihentikan sesuai kebutuhan.

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)

Pemeriksaan Singkat: Efek dan Hasil

Ingat kembali cara efek mengirimkan hasilnya kepada pereduksi.

Ringkasan: Efek dan Dependensi

Anda telah mempelajari cara TCA menangani efek samping dan injeksi:

  • Pereduksi tetap murni dan mengembalikan nilai Effect; .none berarti tidak ada pekerjaan.
  • .run menjalankan pekerjaan asinkron dan mengirimkan hasilnya kembali melalui await send(.action).
  • Kesalahan ditangani dengan blok catch milik efek.
  • @Dependency menyuntikkan layanan seperti jam atau klien Anda sendiri, yang dideklarasikan melalui DependencyKey dan DependencyValues.
  • Efek yang berjalan lama dapat dibuat cancellable berdasarkan ID.

Selanjutnya, Anda akan menyusun fitur-fitur bersama dan mengujinya secara menyeluruh.

import ComposableArchitecture

// Recap: pure reducer + Effect.run for async work
// + @Dependency for testable, injectable services.
Gratis untuk memulai

Belajar Swift dengan tutor AI — gratis

Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.

Kursus
122
Pelajaran
409

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Efek dan Dependensi” gratis?

Ya — teks lengkap “Efek dan Dependensi” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Swift Academy, upgrade ke CoddyKit PRO. Kursus Swift Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Efek dan Dependensi”?

Tangani efek samping dan injeksikan dependensi. Kamu berlatih Swift Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Swift Academy?

Tidak diperlukan pengalaman sebelumnya. Swift Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.

Berapa lama pelajaran “Efek dan Dependensi” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Swift Academy ini?

Ya. Setiap pelajaran Swift Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. State, Action, dan Reducer
  2. Store dan Integrasi SwiftUI
  3. Efek dan Dependensi
  4. Menyusun dan Menguji Fitur
← Kembali ke Swift Academy