0Pricing
Swift Academy · Lekcja

Stan, akcja i reducer

Modelowanie funkcji jako czystych reducerów operujących na stanie.

Stan, akcja i reducer to bezpłatna lekcja Swift Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Swift Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Swift Academy zawiera 4 lekcji w sumie.

Czym jest Composable Architecture

Composable Architecture, w skrócie TCA, to biblioteka do tworzenia aplikacji Swift o spójnej, testowalnej strukturze. Opiera się na trzech elementach: State, który opisuje dane funkcjonalności, Action, który opisuje każde możliwe zdarzenie, oraz Reducer, który zmienia stan w odpowiedzi na akcje.

Ten jednokierunkowy przepływ sprawia, że funkcjonalności są przewidywalne i łatwe do testowania.

import ComposableArchitecture

// State holds data, Action describes events,
// a Reducer turns (state, action) into the next state.

Makro @Reducer

Funkcjonalność definiuje się jako typ oznaczony makrem @Reducer. Makro generuje kod pomocniczy i pozwala zadeklarować State, Action oraz body reduktora razem, w ramach jednej spójnej jednostki.

Zgodnie z konwencją typ nosi nazwę funkcjonalności, na przykład CounterFeature.

import ComposableArchitecture

@Reducer
struct CounterFeature {
    // State, Action, and body go here
}

Definiowanie State

State jest zwykle strukturą przechowującą wszystkie dane potrzebne funkcjonalności. Oznaczenie go za pomocą @ObservableState pozwala SwiftUI precyzyjnie obserwować zmiany i ponownie renderować tylko to, czego dotyczą.

Stan powinien być minimalny, a wartości pochodne należy obliczać, aby zachować jedno źródło prawdy.

import ComposableArchitecture

@Reducer
struct CounterFeature {
    @ObservableState
    struct State: Equatable {
        var count = 0
    }
}

Definiowanie Action

Action to enum zawierający każde zdarzenie, które może obsłużyć funkcjonalność: kliknięcia użytkownika, odpowiedzi, tyknięcia timera i tak dalej. Każdy przypadek opisuje coś, co się wydarzyło, a nie polecenie bezpośredniej modyfikacji stanu.

Jasne nazwy akcji sprawiają, że działanie funkcjonalności samo wyjaśnia swoje przeznaczenie.

import ComposableArchitecture

@Reducer
struct CounterFeature {
    @ObservableState
    struct State: Equatable { var count = 0 }

    enum Action {
        case incrementTapped
        case decrementTapped
    }
}

Ciało Reducer

Logika reduktora znajduje się w obliczanej właściwości body, która zwraca pewien obiekt typu ReducerOf<Self>. W jej wnętrzu używa się Reduce z domknięciem otrzymującym zmienny state oraz przychodzącą action.

Należy przełączyć się na podstawie akcji i odpowiednio zmodyfikować stan.

import ComposableArchitecture

@Reducer
struct CounterFeature {
    @ObservableState
    struct State: Equatable { var count = 0 }
    enum Action { case incrementTapped, decrementTapped }

    var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .incrementTapped:
                state.count += 1
                return .none
            case .decrementTapped:
                state.count -= 1
                return .none
            }
        }
    }
}

Zwracanie efektów

Każda gałąź reduktora musi zwracać obiekt typu Effect. Zwrócenie .none oznacza, że po zmianie stanu nie ma już żadnej asynchronicznej pracy do wykonania.

Jeśli potrzebne są efekty uboczne, takie jak wywołanie sieciowe, należy zwrócić efekt wykonujący tę pracę. Efekty zostaną omówione w późniejszej lekcji.

import ComposableArchitecture

// Every reducer branch returns an Effect.
// No side effect needed? Return .none.
// Need async work? Return an effect describing it.
Reduce { state, action in
    state.count += 1
    return .none
}

Mutacje State są scentralizowane

Podstawowa zasada TCA mówi, że tylko reducer modyfikuje stan i robi to wyłącznie w odpowiedzi na akcje. Widoki nigdy nie zmieniają stanu bezpośrednio — wysyłają akcje.

To jedno, centralne miejsce mutacji sprawia, że przepływ danych jest łatwy do śledzenia i testowania.

import ComposableArchitecture

// Views send actions; the reducer mutates state.
// store.send(.incrementTapped)  ->  state.count += 1
// No direct state mutation outside the reducer.

Modelowanie danych wejściowych użytkownika w State

Funkcjonalności oparte na formularzach przechowują edytowalne pola w State i dodają akcje obsługujące ich zmiany. Użycie bindingów dla właściwości pozwala kontrolkom SwiftUI aktualizować je za pośrednictwem akcji w sposób bezpieczny typowo.

W tym przykładzie funkcjonalność śledzi pole tekstowe i przełącznik.

import ComposableArchitecture

@Reducer
struct FormFeature {
    @ObservableState
    struct State: Equatable {
        var name = ""
        var isSubscribed = false
    }
    enum Action: BindableAction {
        case binding(BindingAction<State>)
    }
    var body: some ReducerOf<Self> {
        BindingReducer()
    }
}

Akcje z wartościami powiązanymi

Akcje mogą przenosić dane za pomocą wartości powiązanych. W ten sposób modeluje się zwracane wyniki, takie jak wczytany element lub błąd, aby reducer mógł zapisać je w stanie.

W tym przykładzie akcja odpowiedzi przenosi pobraną liczbę.

import ComposableArchitecture

@Reducer
struct NumberFeature {
    @ObservableState
    struct State: Equatable { var value = 0 }
    enum Action {
        case reloadTapped
        case responseReceived(Int)
    }
    var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .reloadTapped:
                return .none
            case let .responseReceived(value):
                state.value = value
                return .none
            }
        }
    }
}

Dlaczego State zgodny z Equatable pomaga

Zgodność State z Equatable pozwala TCA wykrywać, czy stan rzeczywiście się zmienił, co umożliwia precyzyjne aktualizacje widoków i wyczerpujące testowanie. To niewielkie wymaganie przynosi duże korzyści.

Większość typów stanu może bez dodatkowej pracy przyjąć Equatable, ponieważ ich przechowywane właściwości już go przyjmują.

import ComposableArchitecture

@ObservableState
struct State: Equatable {
    var count = 0
    var title = ""
}
// Equatable enables change detection and test assertions.

Jak wygląda kompletna funkcjonalność

Ukończona funkcjonalność jest czytelna od góry do dołu: najpierw znajduje się makro, następnie obserwowalny stan, enum akcji i ciało reduktora. Cała funkcjonalność mieści się w jednym typie, dzięki czemu elementy TCA można komponować i łatwo przeglądać.

Ten spójny układ powtarza się w każdej funkcjonalności aplikacji.

import ComposableArchitecture

@Reducer
struct CounterFeature {
    @ObservableState
    struct State: Equatable { var count = 0 }
    enum Action { case incrementTapped, decrementTapped }
    var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .incrementTapped: state.count += 1; return .none
            case .decrementTapped: state.count -= 1; return .none
            }
        }
    }
}

Szybkie sprawdzenie: trzy elementy

Przypomnij sobie role State, Action i Reducer w TCA.

Podsumowanie: State, Action i Reducer

Poznano najważniejsze elementy funkcjonalności TCA:

  • @Reducer definiuje typ funkcjonalności zawierający wszystko w jednym miejscu.
  • @ObservableState umieszczone w strukturze przechowuje dane funkcjonalności i umożliwia ich precyzyjną obserwację.
  • Enum Action zawiera każde zdarzenie, opcjonalnie wraz z wartościami powiązanymi.
  • body reduktora używa Reduce do modyfikowania stanu i zwracania Effect, a gdy efekt uboczny nie jest potrzebny, zwraca .none.
  • Tylko reducer modyfikuje stan, dzięki czemu przepływ danych pozostaje przewidywalny.

Następnie połączysz tę funkcjonalność ze SwiftUI za pomocą Store.

import ComposableArchitecture

// Recap: @Reducer + State + Action + body(Reduce)
// One type, one source of truth, predictable updates.

Często zadawane pytania

Czy lekcja „Stan, akcja i reducer” jest bezpłatna?

Tak — pełny tekst „Stan, akcja i reducer” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Swift Academy, przejdź na CoddyKit PRO. Kurs Swift Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Stan, akcja i reducer”?

Modelowanie funkcji jako czystych reducerów operujących na stanie. Ćwiczysz Swift Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Swift Academy?

Nie wymagamy żadnego doświadczenia. Swift Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.

Ile czasu zajmuje lekcja „Stan, akcja i reducer”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Swift Academy?

Tak. Każda lekcja Swift Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Stan, akcja i reducer
  2. Store i integracja z SwiftUI
  3. Efekty i zależności
  4. Komponowanie i testowanie funkcji
← Powrót do Swift Academy