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