@StateObject adalah property wrapper di SwiftUI yang membuat dan memiliki instance ObservableObject sepanjang siklus hidup View. Ketika View pertama kali muncul di layar, @StateObject menginisialisasi objek dan menyimpannya hingga View dihapus dari memori. Ini menjamin bahwa data tidak akan direset saat pembangunan ulang antarmuka — misalnya, saat mengganti tema atau memperbarui View induk. Menurut Apple Developer Documentation (2025), @StateObject harus digunakan sebagai sumber kebenaran utama (source of truth) untuk ObservableObject dalam hierarki SwiftUI, sementara View anak menerima objek yang sudah dibuat melalui @ObservedObject atau @EnvironmentObject.
Poin Utama
@StateObject adalah property wrapper yang diperkenalkan di iOS 14 yang memungkinkan View untuk membuat dan memiliki instance dari kelas yang sesuai dengan protokol ObservableObject. Berbeda dengan @State yang bekerja dengan tipe nilai (struct), @StateObject ditujukan untuk tipe referensi — kelas yang dapat memberi tahu SwiftUI tentang perubahan properti mereka.
Ketika View menggunakan @StateObject var viewModel: MyViewModel, SwiftUI secara otomatis membuat instance MyViewModel saat pertama kali View ditampilkan dan menyimpannya di penyimpanan khusus framework. Pada setiap pembaruan View (misalnya, saat perubahan state induk), SwiftUI tidak membuat ulang objek — ia menggunakan instance yang sudah ada hingga View dihapus dari hierarki.
Menurut Apple WWDC Session 10137 (2024), @StateObject memecahkan masalah kehilangan data saat pembangunan ulang View yang ada di iOS 13, ketika pengembang harus membuat ObservableObject di View induk dan meneruskannya melalui inisialisator. Ini menyebabkan duplikasi kode dan risiko pembuatan ulang objek yang tidak disengaja.
import SwiftUI
class CounterViewModel: ObservableObject {
@Published var count: Int = 0
func increment() {
count += 1
}
}
struct CounterView: View {
@StateObject var viewModel = CounterViewModel()
var body: some View {
VStack {
Text("Jumlah: \(viewModel.count)")
Button("Tambah", action: viewModel.increment)
}
}
}
Mekanisme @StateObject didasarkan pada integrasi SwiftUI dengan framework Combine. Ketika ObservableObject menandai propertinya dengan atribut @Published, SwiftUI secara otomatis berlangganan perubahan melalui publisher yang tertanam dalam protokol ObservableObject. Saat properti yang dipublikasikan berubah, objek mengirim sinyal melalui publisher objectWillChange, yang memicu penggambaran ulang semua View yang mengamati objek ini.
SwiftUI menyimpan instance ObservableObject di penyimpanan khusus yang terikat pada instance View tertentu. Penyimpanan ini dibuat satu kali pada render pertama dan ada hingga penghancuran View. Inilah mengapa @StateObject menjamin stabilitas referensi ke objek — SwiftUI mengelola memori secara otomatis, tanpa bergantung pada inisialisator View.
Menurut objc.io — Thinking in SwiftUI (2025), implementasi internal @StateObject menggunakan mekanisme yang mirip dengan @State, tetapi untuk tipe referensi: SwiftUI membuat wrapper boxing di sekitar objek dan mengelola siklus hidupnya melalui alokator sendiri, yang dioptimalkan untuk pembangunan ulang hierarki View yang sering.
Perbedaan utama antara @StateObject dan @ObservedObject terletak pada siapa yang memiliki objek. @StateObject membuat dan menyimpan objek — ia adalah pemilik. @ObservedObject hanya mengamati objek yang dibuat di tempat lain dan diteruskan melalui inisialisator atau properti.
| Karakteristik | @StateObject | @ObservedObject |
|---|---|---|
| Kepemilikan | Membuat dan memiliki objek | Hanya mengamati |
| Inisialisasi | Di dalam View melalui init/default | Dari luar, diteruskan melalui parameter |
| Siklus hidup | Terikat pada siklus hidup View | Tidak dikendalikan oleh View |
| Pembuatan ulang | Tidak dibuat ulang saat pembaruan | Dapat diganti dari luar |
| Versi iOS | iOS 14+ | iOS 13+ |
Aturannya sederhana: jika View membuat ObservableObject — gunakan @StateObject. Jika View hanya menerima objek yang sudah jadi dari induk — gunakan @ObservedObject. Pelanggaran aturan ini menyebabkan baik kehilangan data (jika menggunakan @ObservedObject untuk kepemilikan) atau pembuatan objek yang berlebihan (jika menggunakan @StateObject untuk pengamatan).
@StateObject harus digunakan pada View yang menjadi sumber kebenaran untuk kumpulan data tertentu. Skenario umum termasuk layar dengan view model sendiri, layar root dari tumpukan navigasi, dan presentasi modal yang mengelola state sendiri.
struct ProfileView: View {
@StateObject var viewModel = ProfileViewModel()
var body: some View {
NavigationStack {
Form {
TextField("Name", text: $viewModel.name)
TextField("Email", text: $viewModel.email)
Button("Simpan") {
viewModel.saveProfile()
}
}
.navigationTitle("Profile")
}
}
}
Inisialisasi @StateObject dengan parameter memerlukan sintaks khusus, karena SwiftUI mengelola pembuatan objek secara independen. Anda tidak bisa begitu saja meneruskan parameter ke inisialisator — Anda perlu menggunakan escaping closure atau metode pembuatan terpisah.
Menurut Swift by Sundell (2024), metode paling bersih adalah menggunakan metode pabrik atau closure yang akan dipanggil SwiftUI saat pertama kali membuat objek. Pendekatan alternatif — menginisialisasi ObservableObject di View induk dan meneruskannya melalui @StateObject menggunakan inisialisator standar.
class UserViewModel: ObservableObject {
@Published var user: User
init(user: User) {
self.user = user
}
}
struct UserDetailView: View {
@StateObject var viewModel: UserViewModel
init(user: User) {
_viewModel = StateObject(wrappedValue: UserViewModel(user: user))
}
var body: some View {
Text(viewModel.user.name)
}
}
Penting untuk diingat bahwa inisialisator View dengan @StateObject harus menggunakan garis bawah sebelum nama properti (_viewModel) untuk mengakses property wrapper itu sendiri, bukan nilainya. Ini adalah pola standar Swift untuk bekerja dengan property wrapper di inisialisator.
Kesalahan paling umum adalah menggunakan @ObservedObject alih-alih @StateObject untuk View yang seharusnya memiliki objek. Dalam kasus ini, setiap kali induk dibangun ulang, objek akan dibuat ulang, yang menyebabkan hilangnya semua data yang terkumpul. Kesalahan ini sangat berbahaya dalam hierarki kompleks dengan NavigationStack atau TabView.
Untuk menghindari masalah ini, ikuti aturan sederhana: satu @StateObject per satu sumber kebenaran. Jika data harus dibagikan di beberapa layar — buat @StateObject sekali di View root dan teruskan melalui @ObservedObject atau @EnvironmentObject ke elemen anak.
// ❌ Salah: @ObservedObject untuk memiliki objek
struct BadView: View {
@ObservedObject var vm = ViewModel() // akan dibuat ulang pada setiap pembaruan!
}
// ✅ Benar: @StateObject untuk memiliki
struct GoodView: View {
@StateObject var vm = ViewModel() // dibuat sekali untuk masa hidup View
}
Pertanyaan yang Sering Diajukan
@State bekerja dengan tipe nilai (struct, string, angka) dan menyimpan nilai langsung di penyimpanan SwiftUI. @StateObject bekerja dengan tipe referensi — kelas yang sesuai dengan ObservableObject. @State cocok untuk state lokal sederhana, @StateObject untuk objek kompleks dengan logika dan properti yang dipublikasikan.
Tidak, @StateObject hanya tersedia mulai iOS 14 ke atas. Untuk iOS 13 gunakan @ObservedObject dan buat ObservableObject di View induk melalui @State dengan manajemen siklus hidup manual. Alternatif — gunakan @State dengan struct alih-alih class untuk data yang tidak memerlukan semantik referensi.
View anak akan membuat salinan sendiri dari ObservableObject, sepenuhnya independen dari induk. Perubahan di satu salinan tidak akan tercermin di salinan lain. Ini hampir selalu merupakan kesalahan: gunakan @ObservedObject untuk menerima objek dari induk dan @StateObject hanya untuk membuat objek baru di dalam View.
Objek dihancurkan ketika View yang membuatnya sepenuhnya dihapus dari hierarki SwiftUI. Untuk layar di NavigationStack, ini terjadi saat pop dari tumpukan navigasi. Untuk jendela modal — saat ditutup. Untuk TabView — saat mengganti tab, jika View tidak di-cache.
Gunakan init khusus dengan akses ke property wrapper melalui garis bawah: _viewModel = StateObject(wrappedValue: MyViewModel(param: value)). Pola ini memungkinkan meneruskan parameter apa pun ke ObservableObject, sambil mempertahankan jaminan pembuatan objek satu kali selama masa hidup View.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga