0Pricing
Swift Academy · 课时

状态、操作与归约器

将功能建模为基于状态的纯归约器。

状态、操作与归约器 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。

什么是可组合架构

可组合架构(Composable Architecture,简称 TCA)是一个用于构建 Swift 应用的库,提供一致且易于测试的结构。它围绕三个部分展开:描述功能数据的 State、描述所有可能发生事件的 Action,以及根据操作响应并演进状态的 Reducer。

这种单向数据流让功能行为可预测,也更易于测试。

import ComposableArchitecture

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

@Reducer 宏

功能被定义为一个使用 @Reducer 宏进行注解的类型。该宏会生成支持代码,并让您在一个内聚单元中同时声明 State、Action 和归约器 body。

按照惯例,类型名称会以功能命名,例如 CounterFeature。

import ComposableArchitecture

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

定义状态

State 通常是一个结构体,用于保存功能所需的全部数据。为它添加 @ObservableState 后,SwiftUI 就能精确地观察变化,只重新渲染受影响的部分。

请让状态保持精简,并通过计算获得派生值,从而确保只有一个真实数据源。

import ComposableArchitecture

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

定义操作

Action 是一个枚举,列出功能可以处理的所有事件:用户点击、响应、计时器跳动等。每个枚举项表示已经发生的事情,而不是直接改变状态的命令。

清晰的操作名称能让功能行为实现自我说明。

import ComposableArchitecture

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

    enum Action {
        case incrementTapped
        case decrementTapped
    }
}

归约器 body

归约器逻辑位于一个计算属性 body 中,该属性返回某个 ReducerOf<Self>。在其中,您使用 Reduce 和一个闭包;该闭包接收可变的 state 以及传入的 action。

您可以对操作进行分支处理,并相应地修改状态。

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

返回效果

归约器的每个分支都必须返回一个 Effect。返回 .none 表示状态变化后不需要执行进一步的异步工作。

如果确实需要执行副作用,例如网络调用,您就返回一个执行该工作的效果。您将在后续课程中进一步了解效果。

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
}

集中管理状态变更

TCA 的核心规则是:只有归约器可以修改状态,而且只能响应操作进行修改。视图不会直接改变状态,而是发送操作。

这个集中处理所有变更的单一位置,让数据流易于跟踪和测试。

import ComposableArchitecture

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

在状态中建模用户输入

类似表单的功能会将可编辑字段保存在 State 中,并为变化添加操作。为属性标记绑定后,SwiftUI 控件就能通过操作以类型安全的方式更新这些属性。

这里的功能会跟踪一个文本字段和一个切换控件。

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

带有关联值的操作

操作可以使用关联值携带数据。您可以用这种方式建模返回的结果,例如已加载的项目或错误,以便归约器将它们保存到状态中。

这里的响应操作携带获取到的数字。

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

可比较状态的作用

让 State 遵循 Equatable 后,TCA 就能检测状态是否确实发生了变化,从而支持精确的视图更新和全面测试。这是一项很小的要求,却能带来很大的好处。

大多数状态类型都可以直接采用 Equatable,因为它们存储的属性本身已经符合该协议。

import ComposableArchitecture

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

完整功能的结构

一个完成的功能从上到下依次包含:宏、可观察状态、操作枚举和归约器 body。功能的所有内容都位于同一个类型中,这正是 TCA 功能可组合且便于审查的原因。

这种一致的结构会在应用的每个功能中重复出现。

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

快速检查:三个组成部分

请回忆 State、Action 和 Reducer 在 TCA 中各自的作用。

回顾:State、Action 和 Reducer

您已经了解了 TCA 功能的核心:

  • @Reducer 定义一个功能类型,将所有内容集中在一个位置。
  • 结构体上的 @ObservableState 保存功能数据,并支持精确观察。
  • Action 枚举列出每个事件,也可以携带关联值。
  • 归约器 body 使用 Reduce 修改状态并返回 Effect;不需要副作用时返回 .none。
  • 只有归约器可以修改状态,从而让数据流保持可预测。

接下来,您将使用 Store 将这个功能连接到 SwiftUI。

import ComposableArchitecture

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

常见问题解答

「状态、操作与归约器」课时是免费的吗?

是的 — 「状态、操作与归约器」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。

「状态、操作与归约器」这节课中我会学到什么?

将功能建模为基于状态的纯归约器。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Swift Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「状态、操作与归约器」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Swift Academy 课中编写并运行代码吗?

能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 状态、操作与归约器
  2. Store 与 SwiftUI 集成
  3. 副作用与依赖
  4. 组合和测试功能
← 返回 Swift Academy