Section 3/131 menit

3. Sintaks Dasar

3. Sintaks Dasar

Deklarasi

swift
import Observation

// Cukup tambahkan @Observable — tidak perlu ObservableObject, tidak perlu @Published.
// Berlaku untuk class (reference type) — struct tidak bisa @Observable karena
// struct tidak punya identity yang stable untuk observation.
@Observable
final class ProductViewModel {
    // Semua stored property otomatis di-observe — tidak perlu @Published.
    var products: [Product] = []
    var searchQuery: String = ""
    var isLoading: Bool = false
    var selectedCategory: Category = .all
    var errorMessage: String? = nil

    // Computed property juga otomatis di-track berdasarkan stored property
    // yang dibaca di dalamnya.
    var filteredProducts: [Product] {
        if searchQuery.isEmpty { return products }
        return products.filter { $0.name.localizedCaseInsensitiveContains(searchQuery) }
    }
}

Penggunaan di SwiftUI

swift
struct ProductListView: View {
    // Tidak perlu @StateObject/@ObservedObject/@EnvironmentObject —
    // cukup simpan sebagai stored property biasa atau gunakan @State untuk ownership.
    @State private var viewModel = ProductViewModel()

    var body: some View {
        NavigationStack {
            List(viewModel.filteredProducts) { product in  // track: filteredProducts
                ProductRow(product: product)
            }
            .searchable(text: $viewModel.searchQuery)      // track: searchQuery
            .overlay {
                if viewModel.isLoading {                   // track: isLoading
                    ProgressView()
                }
            }
            .task {
                await viewModel.loadProducts()
            }
        }
    }
}

// Passing ke child view — tidak perlu @ObservedObject, cukup var biasa.
// SwiftUI otomatis track property mana yang dibaca di body child view.
struct ProductRow: View {
    var product: Product  // nilai yang sudah di-copy — tidak di-observe langsung

    var body: some View {
        Text(product.name)
    }
}

// Passing viewModel ke child — child menerima reference ke object yang sama.
struct ProductDetailView: View {
    var viewModel: ProductViewModel  // tidak perlu @ObservedObject

    var body: some View {
        Text(viewModel.selectedCategory.rawValue)  // track: selectedCategory
    }
}

Dengan @Environment (Pengganti @EnvironmentObject)

swift
// Inject via .environment() — type-safe, tidak perlu @EnvironmentObject
struct MyApp: App {
    @State private var authViewModel = AuthViewModel()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(authViewModel)  // inject sebagai environment value
        }
    }
}

// Konsumsi di child view
struct ProfileView: View {
    @Environment(AuthViewModel.self) private var auth  // type-safe, compile error jika lupa inject

    var body: some View {
        Text("Hello, \(auth.currentUser?.name ?? "Guest")")
    }
}