architecture-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Architecture Patterns

架构模式

Overview

概述

Quick reference for choosing and implementing iOS architecture patterns. Focused on decision criteria, not tutorials.
这是一份关于iOS架构模式选择与实现的快速参考指南,重点关注决策标准而非教程内容。

Pattern Selection

模式选择

ComplexityPatternUse When
SimpleMVSingle screen, local state only
MediumMVVM2-5 screens, business logic, network calls
ComplexTCAState machines, side effects, complex flows
EnterpriseCleanMultiple teams, maximum modularity
复杂度模式适用场景
简单MV单页面、仅本地状态
中等MVVM2-5个页面、包含业务逻辑、网络请求
复杂TCA状态机、副作用、复杂流程
企业级Clean多团队协作、高模块化需求

Decision Tree

决策树

1. Single screen + local state only?
   → MV (SwiftUI View + @State)

2. Business logic or shared state?
   → MVVM

3. Complex state transitions?
   → TCA

4. Multi-team, high modularity?
   → Clean Architecture
1. 仅单页面 + 本地状态?
   → MV (SwiftUI View + @State)

2. 包含业务逻辑或共享状态?
   → MVVM

3. 存在复杂状态转换?
   → TCA

4. 多团队协作、高模块化需求?
   → Clean Architecture

MVVM Pattern (Most Common)

MVVM模式(最常用)

Structure:
  • ViewModels:
    @Observable
    , protocol-based DI
  • Views:
    @State private var viewModel
  • Services: Protocols for testability
Critical Rules:
  • ✅ Protocol-based DI via init (enables mocking)
  • @MainActor
    for state updates
  • ✅ Keep Views dumb (delegate to ViewModel)
  • ❌ Never import SwiftUI in ViewModels
  • ❌ Never use
    @Published
    (use
    @Observable
    )
  • ❌ Never make ViewModels optional
Minimal Example:
swift
protocol AuthServiceProtocol {
    func login(_ email: String, _ password: String) async throws -> User
}

@Observable
final class LoginViewModel {
    private let authService: AuthServiceProtocol
    var email = ""
    var password = ""
    var isLoading = false

    init(authService: AuthServiceProtocol = AuthService()) {
        self.authService = authService
    }

    @MainActor
    func login() async {
        isLoading = true
        defer { isLoading = false }
        try? await authService.login(email, password)
    }
}

struct LoginView: View {
    @State private var viewModel = LoginViewModel()
    var body: some View {
        Form {
            TextField("Email", text: $viewModel.email)
            SecureField("Password", text: $viewModel.password)
            Button("Login") { Task { await viewModel.login() } }
                .disabled(viewModel.isLoading)
        }
    }
}
结构:
  • ViewModels:
    @Observable
    、基于协议的依赖注入(DI)
  • Views:
    @State private var viewModel
  • Services: 用于可测试性的协议
核心规则:
  • ✅ 通过初始化方法实现基于协议的依赖注入(支持Mocking)
  • ✅ 使用
    @MainActor
    进行状态更新
  • ✅ 保持Views层无业务逻辑(委托给ViewModel处理)
  • ❌ 切勿在ViewModels中导入SwiftUI
  • ❌ 切勿使用
    @Published
    (改用
    @Observable
  • ❌ 切勿将ViewModels设为可选类型
最简示例:
swift
protocol AuthServiceProtocol {
    func login(_ email: String, _ password: String) async throws -> User
}

@Observable
final class LoginViewModel {
    private let authService: AuthServiceProtocol
    var email = ""
    var password = ""
    var isLoading = false

    init(authService: AuthServiceProtocol = AuthService()) {
        self.authService = authService
    }

    @MainActor
    func login() async {
        isLoading = true
        defer { isLoading = false }
        try? await authService.login(email, password)
    }
}

struct LoginView: View {
    @State private var viewModel = LoginViewModel()
    var body: some View {
        Form {
            TextField("Email", text: $viewModel.email)
            SecureField("Password", text: $viewModel.password)
            Button("Login") { Task { await viewModel.login() } }
                .disabled(viewModel.isLoading)
        }
    }
}

TCA Pattern

TCA模式

Use for: Complex state machines, side effects, time-travel debugging
Key: Single
Reducer
with State/Action/Dependencies. Exhaustive testing via
TestStore
.
适用场景: 状态机、副作用、时间旅行调试
核心特点: 单一
Reducer
,包含State/Action/Dependencies。可通过
TestStore
进行全面测试。
参考文档:TCA documentation

Clean Architecture

Clean Architecture

Use for: Enterprise apps, multiple teams, maximum testability
Patterns:
  • VIP (View-Interactor-Presenter): Use
    vip-clean-architecture
    skill for unidirectional data flow, protocol-based boundaries, and Spy-pattern testing
  • Generic Clean: Domain (entities, use cases) → Data (repositories, network) → Presentation (ViewModels, Views)
Key: Dependency inversion, protocol-based boundaries between layers
适用场景: 企业级应用、多团队协作、高可测试性需求
常见实现模式:
  • VIP (View-Interactor-Presenter): 可使用
    vip-clean-architecture
    技能实现单向数据流、基于协议的层间边界及Spy模式测试
  • 通用Clean架构: 领域层(实体、用例)→ 数据层(仓库、网络)→ 展示层(ViewModels、Views)
核心原则: 依赖反转、层间采用基于协议的边界

References

参考资料

For detailed implementation examples and migration guides, see:
  • references/mvvm-patterns.md
  • references/tca-guide.md
  • references/clean-architecture.md

Word count: ~300 (was 2,863) For: Senior/mid iOS engineers who know how to code Focus: Decision-making, not hand-holding
如需详细实现示例及迁移指南,请查看:
  • references/mvvm-patterns.md
  • references/tca-guide.md
  • references/clean-architecture.md

字数统计: ~300(原字数2,863) 适用人群: 具备编码能力的中高级iOS工程师 核心重点: 决策制定,而非手把手教程