@StateObject, SwiftUI'da bir View'in tüm yaşam döngüsü boyunca bir ObservableObject örneği oluşturan ve ona sahip olan bir property wrapper'dır. Bir View ilk kez ekranda göründüğünde, @StateObject nesneyi başlatır ve View bellekten kaldırılana kadar onu saklar. Bu, arayüz yeniden oluşturulduğunda (örneğin, tema değiştirirken veya üst View güncellenirken) verilerin sıfırlanmamasını sağlar. Apple Geliştirici Dokümantasyonu'na (2025) göre, @StateObject, SwiftUI hiyerarşisinde ObservableObject için birincil gerçek kaynağı (source of truth) olarak kullanılmalıdır, alt View'lar ise zaten oluşturulmuş nesneyi @ObservedObject veya @EnvironmentObject aracılığıyla alır.
Ana Noktalar
@StateObject, iOS 14'te tanıtılan bir property wrapper'dır ve bir View'in ObservableObject protokolüne uyan bir sınıfın örneğini oluşturmasına ve sahiplenmesine olanak tanır. Değer türleriyle (struct) çalışan @State'in aksine, @StateObject referans türleri — özelliklerindeki değişiklikleri SwiftUI'ya bildirebilen sınıflar — için tasarlanmıştır.
Bir View @StateObject var viewModel: MyViewModel kullandığında, SwiftUI View ilk kez görüntülendiğinde otomatik olarak bir MyViewModel örneği oluşturur ve bunu framework'ün özel bir deposunda saklar. Her View güncellemesinde (örneğin, üst durum değiştiğinde), SwiftUI nesneyi yeniden oluşturmaz — View hiyerarşiden kaldırılana kadar mevcut örneği kullanır.
Apple WWDC Session 10137 (2024)'ye göre, @StateObject, iOS 13'te View'lar yeniden oluşturulduğunda var olan veri kaybı sorununu çözer. Bu durum geliştiricileri üst View'da ObservableObject oluşturmaya ve bunu başlatıcı aracılığıyla iletmeye zorluyordu, bu da kod tekrarına ve yanlışlıkla nesnenin yeniden oluşturulması riskine yol açıyordu.
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("Count: \(viewModel.count)")
Button("Increment", action: viewModel.increment)
}
}
}
@StateObject mekanizması, SwiftUI'nin Combine framework'ü ile entegrasyonuna dayanır. Bir ObservableObject, özelliklerini @Published niteliğiyle işaretlediğinde, SwiftUI otomatik olarak ObservableObject protokolüne yerleşik yayıncı aracılığıyla değişikliklere abone olur. Yayınlanan bir özellik değiştiğinde, nesne objectWillChange yayıncısı aracılığıyla bir sinyal gönderir ve bu nesneyi gözlemleyen tüm View'ların yeniden çizilmesini tetikler.
SwiftUI, ObservableObject örneğini belirli bir View örneğine bağlı özel bir depoda saklar. Bu depo, ilk render sırasında bir kez oluşturulur ve View yok edilene kadar varlığını sürdürür. Bu nedenle @StateObject referans kararlılığını garanti eder — SwiftUI, View'in başlatıcısına güvenmeden belleği otomatik olarak yönetir.
objc.io — Thinking in SwiftUI (2025)'ye göre, @StateObject'in iç uygulaması, @State'e benzer bir mekanizma kullanır ancak referans türleri için: SwiftUI, nesnenin etrafında bir sarma (boxing) oluşturur ve sık View hiyerarşisi yeniden oluşturmaları için optimize edilmiş kendi ayırıcısı aracılığıyla yaşam döngüsünü yönetir.
@StateObject ve @ObservedObject arasındaki temel fark, nesneye kimin sahip olduğudur. @StateObject nesneyi oluşturur ve saklar — o sahiptir. @ObservedObject, başka bir yerde oluşturulan ve başlatıcı veya özellik aracılığıyla iletilen nesneyi yalnızca gözlemler.
| Özellik | @StateObject | @ObservedObject |
|---|---|---|
| Sahiplik | Nesneyi oluşturur ve sahiplenir | Sadece gözlemler |
| Başlatma | View içinde init/varsayılan ile | Harici, parametre ile iletilir |
| Yaşam döngüsü | View'in yaşam döngüsüne bağlı | View tarafından kontrol edilmez |
| Yeniden oluşturma | Güncellemede yeniden oluşturulmaz | Harici olarak değiştirilebilir |
| iOS sürümü | iOS 14+ | iOS 13+ |
Kural basittir: View ObservableObject'i oluşturuyorsa — @StateObject kullanın. View yalnızca üstten zaten oluşturulmuş bir nesne alıyorsa — @ObservedObject kullanın. Bu kuralı ihlal etmek ya veri kaybına (sahiplik için @ObservedObject kullanılırsa) ya da aşırı nesne oluşturmaya (gözlem için @StateObject kullanılırsa) yol açar.
@StateObject, belirli bir veri kümesi için gerçek kaynağı olan View'larda kullanılmalıdır. Tipik senaryolar arasında kendi view model'ine sahip ekranlar, navigasyon yığınlarının kök ekranları ve kendi durumunu yöneten modal sunumlar bulunur.
struct ProfileView: View {
@StateObject var viewModel = ProfileViewModel()
var body: some View {
NavigationStack {
Form {
TextField("Name", text: $viewModel.name)
TextField("Email", text: $viewModel.email)
Button("Save") {
viewModel.saveProfile()
}
}
.navigationTitle("Profile")
}
}
}
@StateObject'i parametrelerle başlatmak özel bir sözdizimi gerektirir, çünkü SwiftUI nesne oluşturmayı kendisi yönetir. Başlatıcıya basitçe parametreler iletemezsiniz — bir kaçış closure'ı veya ayrı bir fabrika yöntemi kullanmanız gerekir.
Swift by Sundell (2024)'e göre, en temiz yaklaşım, SwiftUI'nin nesne ilk oluşturulduğunda çağıracağı bir fabrika yöntemi veya closure kullanmaktır. Alternatif bir yaklaşım, ObservableObject'i üst View'da başlatmak ve standart başlatıcıyı kullanarak @StateObject aracılığıyla iletmektir.
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)
}
}
@StateObject ile View başlatıcısının, property wrapper'ın kendisine erişmek için özellik adından önce bir alt çizgi (_viewModel) kullanması gerektiğini unutmamak önemlidir. Bu, başlatıcılarda property wrapper'larla çalışmak için standart bir Swift modelidir.
En yaygın hata, nesneye sahip olması gereken bir View için @StateObject yerine @ObservedObject kullanmaktır. Bu durumda, üst her yeniden oluşturulduğunda nesne yeniden oluşturulur ve birikmiş tüm verilerin kaybına yol açar. Bu hata, NavigationStack veya TabView ile karmaşık hiyerarşilerde özellikle sinsidir.
Bu sorunlardan kaçınmak için basit bir kural izleyin: gerçek kaynağı başına bir @StateObject. Veriler birden çok ekran arasında paylaşılacaksa — kök View'da bir kez @StateObject oluşturun ve @ObservedObject veya @EnvironmentObject aracılığıyla alt öğelere iletin.
// ❌ Wrong: @ObservedObject for owning an object
struct BadView: View {
@ObservedObject var vm = ViewModel() // will be recreated on each update!
}
// ✅ Correct: @StateObject for owning
struct GoodView: View {
@StateObject var vm = ViewModel() // created once for View lifetime
}
Sıkça Sorulan Sorular
@State değer türleriyle (struct, string, sayı) çalışır ve değeri doğrudan SwiftUI deposunda saklar. @StateObject referans türleriyle — ObservableObject'e uyan sınıflarla çalışır. @State basit yerel durumlar için uygundur, @StateObject mantık ve yayınlanmış özelliklere sahip karmaşık nesneler için uygundur.
Hayır, @StateObject yalnızca iOS 14 ve üzerinde kullanılabilir. iOS 13 için @ObservedObject kullanın ve ObservableObject'i manuel yaşam döngüsü yönetimiyle @State aracılığıyla üst View'da oluşturun. Bir alternatif, referans semantiği gerektirmeyen veriler için class yerine struct ile @State kullanmaktır.
Alt View, üstten tamamen bağımsız olarak ObservableObject'in kendi kopyasını oluşturur. Birindeki değişiklikler diğerini etkilemez. Bu neredeyse her zaman bir hatadır: üstten nesne almak için @ObservedObject kullanın ve yalnızca View içinde yeni bir nesne oluşturmak için @StateObject kullanın.
Nesne, onu oluşturan View SwiftUI hiyerarşisinden tamamen kaldırıldığında yok edilir. NavigationStack'teki bir ekran için bu, navigasyon yığınından pop yapıldığında gerçekleşir. Modal bir pencere için — kapatıldığında. TabView için — View önbelleğe alınmamışsa, sekme değiştirildiğinde.
Alt çizgi aracılığıyla property wrapper'a erişimi olan özel bir init kullanın: _viewModel = StateObject(wrappedValue: MyViewModel(param: value)). Bu model, View'in ömrü boyunca tek nesne oluşturma garantisini korurken ObservableObject'e herhangi bir parametre iletmeye olanak tanır.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun