Skip to Content
iOS📊 State Management@EnvironmentObject

@EnvironmentObject trong SwiftUI

1. Giới thiệu

@EnvironmentObject chia sẻ data xuyên suốt View hierarchy.

class AppSettings: ObservableObject { @Published var isDarkMode = false @Published var language = "en" } @main struct MyApp: App { @StateObject var settings = AppSettings() var body: some Scene { WindowGroup { ContentView() .environmentObject(settings) } } }

2. Inject và Access

Inject tại root

ContentView() .environmentObject(settings)

Access trong child views

struct ChildView: View { @EnvironmentObject var settings: AppSettings var body: some View { Text("Dark mode: \(settings.isDarkMode ? "On" : "Off")") } }

3. Ví dụ: Theme Manager

class ThemeManager: ObservableObject { @Published var isDarkMode = false @Published var accentColor = Color.blue var backgroundColor: Color { isDarkMode ? .black : .white } var textColor: Color { isDarkMode ? .white : .black } } struct RootView: View { @StateObject var themeManager = ThemeManager() var body: some View { TabView { HomeView() SettingsView() } .environmentObject(themeManager) .preferredColorScheme(themeManager.isDarkMode ? .dark : .light) } } struct HomeView: View { @EnvironmentObject var theme: ThemeManager var body: some View { VStack { Text("Home") .foregroundColor(theme.textColor) } .background(theme.backgroundColor) } } struct SettingsView: View { @EnvironmentObject var theme: ThemeManager var body: some View { Form { Toggle("Dark Mode", isOn: $theme.isDarkMode) ColorPicker("Accent Color", selection: $theme.accentColor) } } }

4. User Session

class UserSession: ObservableObject { @Published var currentUser: User? @Published var isAuthenticated = false func login(email: String, password: String) async throws { // API call currentUser = User(name: "John", email: email) isAuthenticated = true } func logout() { currentUser = nil isAuthenticated = false } } struct AppRootView: View { @StateObject var session = UserSession() var body: some View { Group { if session.isAuthenticated { MainTabView() } else { LoginView() } } .environmentObject(session) } } struct ProfileView: View { @EnvironmentObject var session: UserSession var body: some View { VStack { if let user = session.currentUser { Text("Welcome, \(user.name)") } Button("Logout") { session.logout() } } } }

5. Shopping Cart

class CartManager: ObservableObject { @Published var items: [CartItem] = [] var total: Double { items.reduce(0) { $0 + $1.price * Double($1.quantity) } } var itemCount: Int { items.reduce(0) { $0 + $1.quantity } } func add(_ product: Product) { if let index = items.firstIndex(where: { $0.productId == product.id }) { items[index].quantity += 1 } else { items.append(CartItem(productId: product.id, name: product.name, price: product.price, quantity: 1)) } } func remove(_ item: CartItem) { items.removeAll { $0.id == item.id } } } struct ProductCard: View { let product: Product @EnvironmentObject var cart: CartManager var body: some View { VStack { Text(product.name) Text("$\(product.price, specifier: "%.2f")") Button("Add to Cart") { cart.add(product) } .buttonStyle(.borderedProminent) } } } struct CartBadge: View { @EnvironmentObject var cart: CartManager var body: some View { ZStack(alignment: .topTrailing) { Image(systemName: "cart") if cart.itemCount > 0 { Text("\(cart.itemCount)") .font(.caption2) .foregroundColor(.white) .padding(4) .background(Circle().fill(.red)) .offset(x: 8, y: -8) } } } }

6. Multiple EnvironmentObjects

struct App: App { @StateObject var userSession = UserSession() @StateObject var settings = AppSettings() @StateObject var cart = CartManager() var body: some Scene { WindowGroup { ContentView() .environmentObject(userSession) .environmentObject(settings) .environmentObject(cart) } } }

7. Preview với EnvironmentObject

#Preview { ProductCard(product: Product(name: "iPhone", price: 999)) .environmentObject(CartManager()) }

8. So sánh

Feature@StateObject@EnvironmentObject
Tạo object
Pass qua init
Inject-.environmentObject()
ScopeView đóToàn bộ subtree

📝 Tóm tắt

  • Inject với .environmentObject(object)
  • Access với @EnvironmentObject var obj: Type
  • Dùng cho global state: theme, user session, cart
  • Phải inject trước khi access (crash nếu không có)
  • Dùng chung reference, thay đổi affect tất cả views
Last updated on