SwiftUI中的ViewModel视图管理类

基本概念

在讲解ViewModel之前,我们需要先理解类与结构体的区别。

  • Name
    结构体(struct)
    Type
    struct
    Description
    • 值类型,复制时创建新副本
    • 适合简单的数据模型
    • 用于SwiftUI视图
    • 不可变性和线程安全
  • Name
    类(class)
    Type
    class
    Description
    • 引用类型,共享同一实例
    • 适合复杂的数据管理
    • 用于ViewModel
    • 支持继承和多态

ViewModel基础示例

// 数据模型使用结构体
struct User {
    var name: String
    var age: Int
}

// ViewModel使用类
class UserViewModel: ObservableObject {
    @Published var user: User
    
    init(user: User) {
        self.user = user
    }
    
    func updateName(_ newName: String) {
        user.name = newName
    }
}

ViewModel的角色

ViewModel在SwiftUI中的主要职责。

  • Name
    数据管理
    Type
    data
    Description
    • 状态管理
    • 数据处理
    • 业务逻辑
    • 数据持久化
  • Name
    视图通信
    Type
    communication
    Description
    • 数据绑定
    • 事件处理
    • 状态更新
    • 生命周期管理

ViewModel职责示例

class TodoViewModel: ObservableObject {
    @Published var todos: [Todo] = []
    @Published var isLoading = false
    
    func fetchTodos() {
        isLoading = true
        // 网络请求获取数据
        NetworkService.shared.getTodos { [weak self] result in
            DispatchQueue.main.async {
                self?.isLoading = false
                switch result {
                case .success(let todos):
                    self?.todos = todos
                case .failure(let error):
                    self?.handleError(error)
                }
            }
        }
    }
}

状态管理

ViewModel中的状态管理技术。

  • Name
    状态属性
    Type
    state
    Description
    • @Published属性包装器
    • ObservableObject协议
    • 状态更新
    • 状态同步
  • Name
    生命周期
    Type
    lifecycle
    Description
    • 初始化
    • 清理
    • 内存管理
    • 依赖注入

状态管理示例

class AuthViewModel: ObservableObject {
    @Published var isAuthenticated = false
    @Published var user: User?
    @Published var errorMessage: String?
    
    private var cancellables = Set<AnyCancellable>()
    
    init() {
        // 监听认证状态
        AuthService.shared.$authState
            .sink { [weak self] state in
                self?.isAuthenticated = state != nil
                self?.user = state?.user
            }
            .store(in: &cancellables)
    }
    
    func signOut() {
        AuthService.shared.signOut()
    }
}

最佳实践

ViewModel的设计原则和最佳实践。

  • Name
    设计原则
    Type
    principles
    Description
    • 单一职责
    • 依赖注入
    • 内存管理
    • 错误处理
  • Name
    常见问题
    Type
    issues
    Description
    • 避免循环引用
    • 异步操作处理
    • 状态同步
    • 测试性

ViewModel最佳实践

class ProductViewModel: ObservableObject {
    @Published private(set) var products: [Product] = []
    @Published private(set) var isLoading = false
    @Published private(set) var error: Error?
    
    private let productService: ProductService
    private var cancellables = Set<AnyCancellable>()
    
    init(productService: ProductService = .shared) {
        self.productService = productService
    }
    
    func fetchProducts() {
        isLoading = true
        error = nil
        
        productService.fetchProducts()
            .receive(on: DispatchQueue.main)
            .sink { [weak self] completion in
                self?.isLoading = false
                if case .failure(let error) = completion {
                    self?.error = error
                }
            } receiveValue: { [weak self] products in
                self?.products = products
            }
            .store(in: &cancellables)
    }
}

这篇文章对你有用吗?