Section 2/131 menit
2. Teori & Cara Kerja Internal
2. Teori & Cara Kerja Internal
Observation Framework
@Observable adalah Swift macro yang diperkenalkan di Swift 5.9 (Xcode 15, iOS 17) sebagai bagian dari framework Observation — bukan Combine. Framework ini murni Swift, tidak bergantung pada Objective-C runtime atau Combine.
Ekspansi Macro
Ketika kita menulis:
swift
@Observable
class UserViewModel {
var name: String = ""
var age: Int = 0
}
Swift macro meng-expand kode tersebut menjadi kira-kira:
swift
class UserViewModel: Observable {
// Setiap property yang di-observe dibungkus dengan
// akses ke _$observationRegistrar secara otomatis.
@ObservationIgnored
private var _name: String = ""
var name: String {
get {
// Registrar mencatat: "siapa pun yang sedang mengakses,
// daftarkan dirimu sebagai subscriber untuk property 'name'"
_$observationRegistrar.access(keyPath: \.name)
return _name
}
set {
// Registrar memberitahu semua subscriber bahwa 'name' akan berubah
_$observationRegistrar.withMutation(keyPath: \.name) {
_name = newValue
}
}
}
@ObservationIgnored
private var _age: Int = 0
var age: Int {
get {
_$observationRegistrar.access(keyPath: \.age)
return _age
}
set {
_$observationRegistrar.withMutation(keyPath: \.age) {
_age = newValue
}
}
}
// Registrar ini adalah "pusat kendali" observasi.
// Ia menyimpan mapping: keyPath → Set<Observer>
@ObservationIgnored
private let _$observationRegistrar = ObservationRegistrar()
}
Mekanisme Dependency Tracking Otomatis
Ini adalah perbedaan paling fundamental antara @Observable dan ObservableObject:
swift
ObservableObject:
View subscribe ke OBJECT → satu property berubah → VIEW DI-RENDER ULANG
@Observable:
View membaca property X → SwiftUI MENCATAT bahwa View ini bergantung pada X
Property Y berubah → SwiftUI cek: "apakah ada View yang bergantung pada Y?" → tidak ada → View TIDAK di-render ulang
Property X berubah → SwiftUI cek: "ada View yang bergantung pada X?" → ada → View DI-RENDER ULANG
Dependency tracking ini terjadi secara otomatis saat runtime berdasarkan property mana yang dibaca di dalam body View. Tidak perlu anotasi manual.
swift
@Observable
class DashboardViewModel {
var userName: String = "Ari"
var postCount: Int = 42
var followerCount: Int = 1000
var isLoading: Bool = false
}
// View ini HANYA membaca userName dan postCount.
// SwiftUI mencatat dependensi: [userName, postCount]
// Ketika isLoading atau followerCount berubah → View ini TIDAK di-render ulang.
struct HeaderView: View {
var viewModel: DashboardViewModel
var body: some View {
VStack {
Text(viewModel.userName) // → dependency: userName
Text("\(viewModel.postCount) posts") // → dependency: postCount
}
}
}
ObservationRegistrar
ObservationRegistrar adalah struct internal yang menjadi jantung dari Observation framework. Ia:
- Merekam akses (
access): saat property dibaca, registrar mencatat siapa observer-nya - Memicu mutasi (
withMutation): saat property ditulis, registrar memberitahu semua observer yang bergantung pada property tersebut - Menyimpan mapping per-keyPath:
[PartialKeyPath<T>: Set<AnyObserver>]