# Hướng Dẫn Kiến Trúc > Tài liệu kiến trúc chi tiết cho ứng dụng iOS AppClientBaseSwift. ## Tổng Quan AppClientBaseSwift là ứng dụng iOS native được xây dựng theo mẫu kiến trúc **MVVM (Model-View-ViewModel)** với **SwiftUI** cho UI declarative. Ứng dụng tuân theo các best practices phát triển hiện đại của Apple bao gồm: - **Swift Concurrency** (async/await) - **Combine** cho reactive data binding - **Protocol-oriented programming** để tăng khả năng test - **Keychain Services** cho lưu trữ bảo mật ## Sơ Đồ Kiến Trúc ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ LỚP PRESENTATION │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ SwiftUI Views │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ │ │ SplashView │ │ HomeView │ │ ExploreView │ │ ProfileView │ │ │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ │ │ LoginView │ │RegisterView │ │ForgotPasswd │ │ │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ @StateObject / @EnvironmentObject │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ ViewModels (@MainActor) │ │ │ │ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │ │ │ │ │ AuthViewModel │ │ HomeViewModel │ │ProfileViewModel│ │ │ │ │ └────────────────┘ └────────────────┘ └────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ Dependency Injection (dựa trên Protocol) ┌─────────────────────────────────────────────────────────────────────────┐ │ LỚP SERVICE │ │ ┌─────────────────────────────┐ ┌─────────────────────────────┐ │ │ │ APIService │ │ AuthManager │ │ │ │ • request() │ │ • @Published authState │ │ │ │ • get(), post() │ │ • login(), register() │ │ │ │ • URLSession │ │ • Lưu trữ Keychain │ │ │ └─────────────────────────────┘ └─────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────────┐ │ LỚP DATA │ │ ┌─────────────────────────────┐ ┌─────────────────────────────┐ │ │ │ Models │ │ Constants │ │ │ │ • User (Codable) │ │ • APIConfig │ │ │ │ • HomeItem │ │ • StorageKeys │ │ │ │ • AuthState │ │ • DesignSystem │ │ │ └─────────────────────────────┘ └─────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ ``` ## Chi Tiết Component ### 1. Lớp Presentation #### Views | Component | Trách nhiệm | |-----------|-------------| | `SplashView` | Màn hình splash động, điều hướng trễ | | `ContentView` | Container TabView gốc, routing theo auth state | | `AuthContainerView` | Điều hướng luồng Auth (Login/Đăng ký/Quên MK) | | `HomeView` | Tab Home với lời chào, promo, dịch vụ | | `ExploreView` | Tính năng khám phá và tìm kiếm | | `ProfileView` | Hồ sơ người dùng và cài đặt | #### ViewModels ```swift @MainActor final class HomeViewModel: ObservableObject { @Published var isLoading: Bool = false @Published var items: [HomeItem] = [] @Published var errorMessage: String? private let apiService: APIServiceProtocol func loadData() async { ... } } ``` ### 2. Lớp Service #### APIService HTTP client tuân theo nguyên tắc Single Responsibility: ```swift protocol APIServiceProtocol { func request( endpoint: String, method: HTTPMethod, body: Encodable?, headers: [String: String]? ) async throws -> T } ``` **Tính năng:** - Xử lý request/response generic - Tự động mã hóa/giải mã JSON (snake_case ↔ camelCase) - Tự động thêm Bearer token - Xử lý mã trạng thái HTTP #### AuthManager Singleton quản lý trạng thái xác thực: ```swift final class AuthManager: ObservableObject { @MainActor static let shared = AuthManager() @Published var authState: AuthState = .unknown } ``` **Enum AuthState:** ```swift enum AuthState { case unknown // Trạng thái khởi tạo case unauthenticated // Chưa đăng nhập case authenticated(User) // Đã đăng nhập } ``` ## Luồng Dữ Liệu ```mermaid sequenceDiagram participant V as View participant VM as ViewModel participant S as Service participant API as Backend API V->>VM: Hành động User (tap button) VM->>VM: Đặt isLoading = true VM->>S: await service.request() S->>API: HTTP Request API-->>S: JSON Response S-->>VM: Model đã giải mã VM->>VM: Cập nhật @Published VM-->>V: SwiftUI render lại ``` ## Luồng Xác Thực ```mermaid stateDiagram-v2 [*] --> Unknown: Khởi động App Unknown --> Authenticated: Token hợp lệ Unknown --> Unauthenticated: Không có Token Unauthenticated --> Login Login --> Authenticated: Thành công Login --> Register: Điều hướng Register --> Authenticated: Thành công Authenticated --> HomeScreen HomeScreen --> Unauthenticated: Đăng xuất ``` ## Quyết Định Thiết Kế ### 1. Tại sao MVVM? | Lợi ích | Mô tả | |---------|-------| | Khả năng test | ViewModel có thể test độc lập không cần UI | | Phân tách trách nhiệm | View chỉ hiển thị, logic nằm ở ViewModel | | Tương thích SwiftUI | `@ObservableObject` + `@Published` native | | Cập nhật reactive | UI tự động làm mới dựa trên Combine | ### 2. Tại sao DI dựa trên Protocol? ```swift // Protocol cho phép mock khi test protocol APIServiceProtocol { ... } // Production final class APIService: APIServiceProtocol { ... } // Test mock final class MockAPIService: APIServiceProtocol { ... } ``` ### 3. Tại sao Keychain thay vì UserDefaults? | Keychain | UserDefaults | |----------|--------------| | ✅ Mã hóa khi lưu trữ | ❌ Text thuần | | ✅ Secure enclave | ❌ Có thể truy cập | | ✅ Riêng cho app | ❌ Shared prefs | ### 4. Tại sao @MainActor trên ViewModels? - Đảm bảo tất cả cập nhật `@Published` xảy ra trên main thread - Ngăn chặn vấn đề concurrency với SwiftUI - Contract an toàn thread rõ ràng ## Kiến Trúc Bảo Mật ``` ┌────────────────────────────────────────────────────────────┐ │ CÁC LỚP BẢO MẬT │ ├────────────────────────────────────────────────────────────┤ │ Lớp 1: Bảo mật Transport (HTTPS/TLS) │ │ • Tất cả API calls sử dụng HTTPS │ ├────────────────────────────────────────────────────────────┤ │ Lớp 2: Bảo mật Token (Keychain) │ │ • Access token lưu trong Keychain │ │ • Refresh token lưu trong Keychain │ ├────────────────────────────────────────────────────────────┤ │ Lớp 3: Bảo mật Session │ │ • Kiểm tra hết hạn token │ │ • Tự động refresh token │ ├────────────────────────────────────────────────────────────┤ │ Lớp 4: Validation Input │ │ • Kiểm tra định dạng email │ │ • Kiểm tra độ mạnh mật khẩu │ └────────────────────────────────────────────────────────────┘ ``` ## Hướng Phát Triển | Tính năng | Ưu tiên | Mô tả | |-----------|---------|-------| | Certificate Pinning | Cao | Xác thực chứng chỉ TLS | | Xác thực sinh trắc | Cao | Đăng nhập Face ID / Touch ID | | Chế độ Offline | Trung bình | Cache local với SwiftData | | Push Notifications | Trung bình | Tích hợp APNs | ## Tài Liệu Liên Quan - [README.md](./README.md) - Hướng dẫn bắt đầu nhanh