MVVM Pattern
1. Overview
Phần tiêu đề “1. Overview”View ←→ ViewModel ←→ ModelUI Logic Data2. Model
Phần tiêu đề “2. Model”struct User: Identifiable, Codable { let id: Int let name: String let email: String}3. ViewModel
Phần tiêu đề “3. ViewModel”@MainActorclass UserListViewModel: ObservableObject { @Published var users: [User] = [] @Published var isLoading = false @Published var error: String?
private let service: UserService
init(service: UserService = UserService()) { self.service = service }
func loadUsers() async { isLoading = true error = nil
do { users = try await service.fetchUsers() } catch { self.error = error.localizedDescription }
isLoading = false }
func deleteUser(_ user: User) async { do { try await service.delete(user) users.removeAll { $0.id == user.id } } catch { self.error = error.localizedDescription } }}4. View
Phần tiêu đề “4. View”struct UserListView: View { @StateObject var viewModel = UserListViewModel()
var body: some View { Group { if viewModel.isLoading { ProgressView() } else if let error = viewModel.error { Text(error).foregroundColor(.red) } else { List(viewModel.users) { user in UserRow(user: user) } } } .task { await viewModel.loadUsers() } }}5. Benefits
Phần tiêu đề “5. Benefits”- Testable: ViewModel có thể test riêng
- Reusable: Logic tách khỏi UI
- Maintainable: Clear separation
📝 Best Practices
Phần tiêu đề “📝 Best Practices”- ViewModel là
@MainActorcho UI updates - Dùng
@StateObjectkhi tạo ViewModel - Dùng
@ObservedObjectkhi nhận từ parent