16 KiB
16 KiB
Architecture / Kiến Trúc
EN: Detailed architecture documentation for AppClientBaseSwift iOS application. VI: Tài liệu kiến trúc chi tiết cho ứng dụng iOS AppClientBaseSwift.
Overview / Tổng Quan
AppClientBaseSwift is a native iOS application built using MVVM (Model-View-ViewModel) architecture pattern with SwiftUI for declarative UI. The app follows Apple's modern development best practices including:
- Swift Concurrency (async/await)
- Combine for reactive data binding
- Protocol-oriented programming for testability
- Keychain Services for secure storage
Architecture Diagram / Sơ Đồ Kiến Trúc
┌─────────────────────────────────────────────────────────────────────────┐
│ PRESENTATION LAYER │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ SwiftUI Views │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ SplashView │ │ HomeView │ │ ExploreView │ │ ProfileView │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ LoginView │ │RegisterView │ │ForgotPasswd │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ @StateObject / @EnvironmentObject │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ ViewModels (@MainActor) │ │
│ │ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │ │
│ │ │ AuthViewModel │ │ HomeViewModel │ │ProfileViewModel│ │ │
│ │ │ @Published │ │ @Published │ │ @Published │ │ │
│ │ │ - isLoading │ │ - items │ │ - user │ │ │
│ │ │ - errorMessage │ │ - greeting │ │ - isEditing │ │ │
│ │ └────────────────┘ └────────────────┘ └────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
│
Dependency Injection (Protocol-based)
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ SERVICE LAYER │
│ ┌─────────────────────────────┐ ┌─────────────────────────────┐ │
│ │ APIService │ │ AuthManager │ │
│ │ ┌───────────────────────┐ │ │ ┌───────────────────────┐ │ │
│ │ │ APIServiceProtocol │ │ │ │ @Published authState │ │ │
│ │ │ - request<T>() │ │ │ │ - login() │ │ │
│ │ │ - get(), post() │ │ │ │ - register() │ │ │
│ │ │ - put(), delete() │ │ │ │ - logout() │ │ │
│ │ └───────────────────────┘ │ │ │ - refreshToken() │ │ │
│ │ URLSession │ │ │ Keychain │ │ │
│ └─────────────────────────────┘ └─────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ DATA LAYER │
│ ┌─────────────────────────────┐ ┌─────────────────────────────┐ │
│ │ Models │ │ Constants │ │
│ │ ┌───────────────────────┐ │ │ ┌───────────────────────┐ │ │
│ │ │ User (Codable) │ │ │ │ APIConfig │ │ │
│ │ │ HomeItem │ │ │ │ AppConstants │ │ │
│ │ │ AuthState │ │ │ │ StorageKeys │ │ │
│ │ └───────────────────────┘ │ │ │ DesignSystem │ │ │
│ └─────────────────────────────┘ └─────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
Component Details / Chi Tiết Component
1. Presentation Layer
Views
| Component | Responsibility / Trách nhiệm |
|---|---|
SplashView |
Animated splash screen, delayed navigation |
ContentView |
Root TabView container, auth state routing |
AuthContainerView |
Auth flow navigation (Login/Register/Forgot) |
HomeView |
Home tab with greeting, promo, services |
ExploreView |
Discovery and search features |
ProfileView |
User profile and settings |
ViewModels
@MainActor
final class HomeViewModel: ObservableObject {
// Reactive properties
@Published var isLoading: Bool = false
@Published var items: [HomeItem] = []
@Published var errorMessage: String?
// Dependencies injected via init
private let apiService: APIServiceProtocol
// Async methods using Swift Concurrency
func loadData() async { ... }
}
2. Service Layer
APIService
HTTP client following Single Responsibility Principle:
protocol APIServiceProtocol {
func request<T: Decodable>(
endpoint: String,
method: HTTPMethod,
body: Encodable?,
headers: [String: String]?
) async throws -> T
}
Features:
- Generic request/response handling
- Automatic JSON encoding/decoding (snake_case ↔ camelCase)
- Bearer token injection
- HTTP status code handling
- Error categorization
AuthManager
Singleton for authentication state:
final class AuthManager: ObservableObject {
@MainActor static let shared = AuthManager()
@Published var authState: AuthState = .unknown
// Keychain-backed tokens
var accessToken: String? { get }
var refreshToken: String? { get }
}
AuthState Enum:
enum AuthState {
case unknown // Initial state / Trạng thái khởi tạo
case unauthenticated // Logged out / Chưa đăng nhập
case authenticated(User) // Logged in / Đã đăng nhập
}
3. Data Layer
Models
struct User: Codable, Identifiable, Equatable {
let id: String
let email: String
let name: String
let avatarUrl: String?
let phoneNumber: String?
let isEmailVerified: Bool
let createdAt: Date?
let updatedAt: Date?
}
Constants
Organized into semantic enums:
APIConfig: Base URL, version, timeoutAppConstants: App name, bundle ID, keychain serviceStorageKeys: UserDefaults/Keychain keysDesignSystem: Spacing, corner radius, font sizes
Data Flow / Luồng Dữ Liệu
sequenceDiagram
participant V as View
participant VM as ViewModel
participant S as Service
participant API as Backend API
V->>VM: User Action (button tap)
VM->>VM: Set isLoading = true
VM->>S: await service.request()
S->>API: HTTP Request
API-->>S: JSON Response
S-->>VM: Decoded Model
VM->>VM: Update @Published
VM-->>V: SwiftUI re-render
Authentication Flow / Luồng Xác Thực
stateDiagram-v2
[*] --> Unknown: App Launch
Unknown --> Authenticated: Token Found + Valid
Unknown --> Unauthenticated: No Token
Unauthenticated --> Login: Show Login
Login --> Authenticated: Login Success
Login --> Register: Navigate
Register --> Authenticated: Register Success
Authenticated --> HomeScreen: Show Main App
HomeScreen --> Unauthenticated: Logout
Authenticated --> TokenRefresh: Token Expired
TokenRefresh --> Authenticated: Refresh Success
TokenRefresh --> Unauthenticated: Refresh Failed
Design Decisions / Quyết Định Thiết Kế
1. Why MVVM? / Tại Sao MVVM?
| Benefit / Lợi ích | Description / Mô tả |
|---|---|
| Testability | ViewModel có thể test độc lập không cần UI |
| Separation of Concerns | View chỉ hiển thị, logic nằm ở ViewModel |
| SwiftUI Compatibility | @ObservableObject + @Published native |
| Reactive Updates | Combine-based automatic UI refresh |
2. Why Protocol-based DI?
// Protocol enables mocking for tests
protocol APIServiceProtocol {
func get<T: Decodable>(endpoint: String) async throws -> T
}
// Production implementation
final class APIService: APIServiceProtocol { ... }
// Test mock
final class MockAPIService: APIServiceProtocol { ... }
3. Why Keychain over UserDefaults?
| Keychain | UserDefaults |
|---|---|
| ✅ Encrypted at rest | ❌ Plain text |
| ✅ Secure enclave | ❌ Accessible |
| ✅ App-specific | ❌ Shared prefs |
4. Why @MainActor on ViewModels?
@MainActor
final class HomeViewModel: ObservableObject { ... }
- Ensures all
@Publishedupdates happen on main thread - Prevents concurrency issues with SwiftUI
- Explicit thread safety contract
Security Architecture / Kiến Trúc Bảo Mật
┌────────────────────────────────────────────────────────────┐
│ SECURITY LAYERS │
├────────────────────────────────────────────────────────────┤
│ Layer 1: Transport Security (HTTPS/TLS) │
│ • All API calls use HTTPS │
│ • Certificate pinning (TODO) │
├────────────────────────────────────────────────────────────┤
│ Layer 2: Token Security (Keychain) │
│ • Access token stored in Keychain │
│ • Refresh token stored in Keychain │
│ • kSecClassGenericPassword protection │
├────────────────────────────────────────────────────────────┤
│ Layer 3: Session Security │
│ • Token expiry validation │
│ • Automatic token refresh │
│ • Secure logout (clear all tokens) │
├────────────────────────────────────────────────────────────┤
│ Layer 4: Input Validation │
│ • Email format validation │
│ • Password strength checking │
│ • Form field sanitization │
└────────────────────────────────────────────────────────────┘
Future Considerations / Hướng Phát Triển
| Feature | Priority | Description |
|---|---|---|
| Certificate Pinning | High | TLS certificate validation |
| Biometric Auth | High | Face ID / Touch ID login |
| Offline Mode | Medium | Local caching with SwiftData |
| Push Notifications | Medium | APNs integration |
| Analytics | Low | Event tracking system |
Related Documentation / Tài Liệu Liên Quan
- README.md - Quick start guide
- Swift Enterprise Architect Skill
- Swift Security Skill
- Swift Networking Skill