Section 1/131 menit

1. Masalah yang Dipecahkan

1. Masalah yang Dipecahkan

Era Sebelum Observable: ObservableObject + @Published

Sebelum @Observable hadir di Swift 5.9, SwiftUI menggunakan ObservableObject dari framework Combine:

swift
// Swift 5.x — cara lama
import Combine

class UserViewModel: ObservableObject {
    @Published var name: String = ""
    @Published var email: String = ""
    @Published var isLoading: Bool = false
    var internalCache: [String: Any] = [:]  // juga di-observe, padahal tidak mau
}

Masalah besar ObservableObject:

Masalah 1: Granularitas Terlalu Kasar (Over-notification)

swift
class CartViewModel: ObservableObject {
    @Published var items: [CartItem] = []
    @Published var totalPrice: Double = 0
    @Published var couponCode: String = ""
    @Published var isCheckingOut: Bool = false
}

// View A hanya menampilkan totalPrice.
// View B hanya menampilkan items.
// View C hanya menampilkan couponCode.
//
// Ketika 'isCheckingOut' berubah (tidak relevan untuk A, B, C),
// SEMUA VIEW di-invalidate dan di-render ulang.
// ObservableObject menggunakan objectWillChange publisher —
// satu sinyal untuk SEMUA perubahan property.

objectWillChange adalah all-or-nothing: satu property berubah → semua subscriber dinotifikasi → semua view yang mengobservasi object ini di-render ulang, meski properti yang mereka tampilkan tidak berubah.

Masalah 2: Ketergantungan pada Combine

ObservableObject adalah protocol dari framework Combine — bukan bagian dari Swift standard library. Ini berarti:

  • Di server-side Swift (Linux), Combine tidak tersedia
  • Di UIKit tanpa SwiftUI, harus import Combine hanya untuk state management
  • Testing lebih kompleks karena Combine infrastructure ikut terbawa

Masalah 3: Boilerplate @Published

Setiap property yang ingin di-observe harus diberi anotasi @Published. Jika lupa — property itu tidak di-observe dan UI tidak update. Jika tidak sengaja menambahkan @Published ke property internal — property itu ikut men-trigger re-render yang tidak perlu.

Masalah 4: @EnvironmentObject Tidak Type-Safe

swift
// Lupa inject environmentObject → crash saat runtime, bukan compile error
struct SomeView: View {
    @EnvironmentObject var viewModel: CartViewModel  // crash jika tidak di-inject
}