@StateObject: nedir, @ObservedObject’ten farkı ve örnekler

Yazar: IT Sectr Yayınlanma: 2026-06-19 Okuma süresi: 7 dk

@StateObject, SwiftUI’da bir ObservableObject örneğini doğrudan bir view içinde oluşturmak ve sahiplenmek için kullanılan bir Property Wrapper’dır. SwiftUI, nesnenin view’ın yaşam döngüsü boyunca bir kez başlatılmasını ve sonraki render işlemlerinde yeniden oluşturulmamasını garanti eder. Apple Developer Documentation (2025)’a göre, @StateObject veri kaynağı oluşturan kök view’lar için önerilir. @StateObject, SwiftUI hiyerarşisinde bir ObservableObject’e sahip olmak için doğru seçimdir.

Önemli Noktalar

  • @StateObject — view’da ObservableObject oluşturmak ve sahiplenmek için Property Wrapper
  • Tek örnek — nesne bir kez oluşturulur ve render işlemlerinde yeniden oluşturulmaz
  • Gerçeğin kaynağı — @StateObject tüm hiyerarşi için veri kararlılığını garanti eder
  • @ObservedObject’ten farkı — @ObservedObject nesneye sahip değildir ve kaybedebilir
  • Kök view’lar — @StateObject, nesneyi oluşturan view’da kullanılır

SwiftUI’da @StateObject Nedir?

@StateObject, SwiftUI 2.0’da (iOS 14) tanıtılan ve @ObservedObject ile @State’in yeteneklerini birleştiren bir Property Wrapper’dır. @ObservedObject gibi, ObservableObject değişikliklerine abone olur. @State gibi, verilerin tekrarlanan view yapısı başlatmalarından kurtulmasını garanti eder. @StateObject, view ilk kez ekrana geldiğinde nesneyi bir kez oluşturur ve SwiftUI’nın heap’inde saklar.

@StateObject’ten önce, geliştiriciler view’larda oluşturulanlar da dahil olmak üzere tüm ObservableObject’ler için @ObservedObject kullanıyordu. Bu, üst view güncellendiğinde sık veri kaybına yol açıyor, view yapısı yeniden oluşturuluyor ve @ObservedObject örneği de beraberinde gidiyordu. @StateObject, kararlılık garantisi ekleyerek bu sorunu çözdü.

Temel kural: @StateObject, varsayılan başlatıcıda (let model = ViewModel()) nesneyi oluşturan view’da kullanılır. Bu nesneyi alan alt view’lar @ObservedObject kullanır. Bu ayrım, tüm hiyerarşi boyunca tek bir gerçek kaynağı garanti eder.

@StateObject Yaşam Döngüsü

SwiftUI, @StateObject’in yaşam döngüsünü @State’e benzer bir depolama yöneticisi aracılığıyla yönetir. View ilk kez göründüğünde, SwiftUI nesne için bellek ayırır ve kalıcı bir alanda saklar. Sonraki render işlemlerinde (body çağrıları), nesne yeniden oluşturulmaz—mevcut örnek kullanılır. Nesne, view hiyerarşide olduğu sürece yaşar.

View hiyerarşiden kaldırıldığında, SwiftUI @StateObject’i yok eder ve deinit çağırır. View hiyerarşiye tekrar eklendiğinde yeni bir örnek oluşturulur. Tasarım yaparken bunu dikkate almak önemlidir: view kaldırmaları arasında veriyi korumanız gerekiyorsa, kalıcılık için bir hizmet katmanı (singleton veya DI) veya @AppStorage kullanın.

swift
class TimerViewModel: ObservableObject {
    @Published var seconds: Int = 0
    private var timer: Timer?

    func start() {
        timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
            self.seconds += 1
        }
    }

    deinit {
        timer?.invalidate()
    }
}

struct TimerView: View {
    @StateObject var viewModel = TimerViewModel()

    var body: some View {
        Text("\(viewModel.seconds)s")
            .onAppear { viewModel.start() }
    }
}

Örnekte, TimerViewModel @StateObject aracılığıyla oluşturulur ve TimerView ekranda olduğu sürece yaşar. Zamanlayıcı onAppear’da başlar ve deinit’te durur. @ObservedObject kullanılsaydı, TimerView’ın her render işlemi saniye = 0 olan yeni bir TimerViewModel oluşturur ve zamanlayıcı asla doğru çalışmazdı. @StateObject, viewModel’in benzersiz ve kararlı olmasını garanti eder.

@StateObject vs @ObservedObject: Karşılaştırma

@StateObject ve @ObservedObject arasındaki seçim, nesnenin sahibinin kim olduğuna bağlıdır. View nesneyi oluşturuyorsa—@StateObject. View hazır bir nesne alıyorsa—@ObservedObject. Bu kural o kadar önemlidir ki Xcode, bir başlatıcı aracılığıyla nesne alan alt view’da @StateObject kullanıldığında bir uyarı gösterir.

DurumÖnerilen Wrapper
View, ViewModel() ile model oluşturur@StateObject
View, modeli üstten alır@ObservedObject
Model tek bir view’da kullanılır@StateObject
Model Environment aracılığıyla iletilir@EnvironmentObject
Önizlemeler için model gerekir@ObservedObject + mock

Pratikte, bir projenin başında @StateObject genellikle kök view’da ve @ObservedObject tüm alt view’larda kullanılır. Uygulama büyüdükçe, hiyerarşiyi basitleştirmek için bazı @StateObject örnekleri @EnvironmentObject ile değiştirilebilir. Ancak @StateObject, kendi mantığına sahip modüler ekranlar için en iyi seçim olmaya devam eder.

@StateObject Kullanım Kalıpları

İlk kalıp—@StateObject ile MVVM. ObservableObject olarak ViewModel, @StateObject aracılığıyla view’da oluşturulur. ViewModel, @Published özellikleri ve iş mantığını içerir. View, değişikliklere abone olur ve arayüzü günceller. Bu yaklaşım, test edilebilir yalıtım sağlar: ViewModel, doğrudan bir örnek oluşturarak UI olmadan test edilebilir.

İkinci kalıp—Bağımlılıklarla @StateObject. ViewModel hizmet gerektiriyorsa, parametrelerle başlatma kullanın. Örneğin, @StateObject var viewModel = UserViewModel(api: APIClient.shared). Ancak dikkatli olun: parametreler her body renderında hesaplanır, ancak nesne yalnızca bir kez oluşturulur. SwiftUI, @StateObject’in sonraki başlatmalarını yok sayar.

Üçüncü kalıp—iç içe @StateObject’ler. SwiftUI’da bir view’da birden çok @StateObject bulunabilir, ancak bu nadiren haklıdır. Genellikle bir @StateObject, view’ın tüm veri kümesini yönetir. Mantık çok karmaşık hale gelirse, onu bir @StateObject içindeki @ObservedObject hizmetlerinin bir bileşimine bölün.

swift
struct AppView: View {
    @StateObject var router = NavigationRouter()
    @StateObject var auth = AuthViewModel()

    var body: some View {
        ContentView()
            .environmentObject(router)
            .environmentObject(auth)
    }
}

Örnekte, AppView iki @StateObject oluşturur: gezinmeyi yönetmek için NavigationRouter ve kimlik doğrulama için AuthViewModel. Her iki nesne de environmentObject aracılığıyla Environment’a enjekte edilir. Herhangi bir alt view, başlatıcı zincirinden geçmeden @EnvironmentObject aracılığıyla bunlara erişebilir.

@StateObject ve Parametrelerle Başlatma

@StateObject, herhangi bir parametreyle başlatmayı destekler, ancak önemli bir uyarıyla: başlatıcı yalnızca bir kez çağrılır. Sonraki body render işlemlerinde, parametrelerdeki yeni değerler yok sayılır. Bu, @State var id: Int = 5’i @StateObject var vm = ViewModel(id: id)’ye aktarırsanız, id değiştiğinde ViewModel’in yeni değeri almayacağı anlamına gelir.

Bu sorunu çözmek için senkronizasyon için onReceive veya onAppear kullanın. Combine aracılığıyla ViewModel içinde parametre değişikliklerine abone olun veya parametreleri view düzeyinde .onChange(of:) yöntemiyle iletin. Nesnenin harici değişikliklere dinamik olarak yanıt vermesi gerekiyorsa, @StateObject yerine @ObservedObject kullanmak bir alternatiftir.

swift
struct DetailView: View {
    let itemId: Int
    @StateObject var viewModel = DetailViewModel()

    var body: some View {
        Text(viewModel.title)
            .onAppear { viewModel.load(id: itemId) }
    }
}

Doğru yaklaşım: DetailView, itemId’yi bir let özelliği olarak alır (yapının başlatıcısı aracılığıyla iletilir) ve @StateObject, parametresiz DetailViewModel oluşturur. onAppear’da, iletilen ID için veri yüklemek üzere load(id:) yöntemi çağrılır. Bu, ViewModel’in @StateObject mekanizması tarafından oluşturulmasını, ancak verilerin geçerli ID ile her view görünümünde yüklenmesini garanti eder.

@StateObject ile Sık Yapılan Hatalar

Ana hata—nesneyi bir üstten alan alt view’larda @StateObject kullanmak. ParentView @StateObject model oluşturur ve ChildView @StateObject var model: ModelType (varsayılan parametreyle) bildirirse, ChildView kendi bağımsız örneğini oluşturur. Üst ve alt nesneler bağlantılı olmaz ve birindeki değişiklikler diğerine yansımaz.

İkinci hata—List veya ForEach içinde @StateObject kullanmak. Listenin her öğesi kendi @StateObject’ini oluşturur ve bu da birden çok bağımsız örneğe yol açar. Listeler için doğru yaklaşım, tüm öğelere @ObservedObject aracılığıyla tek bir ObservableObject iletmek veya List içinde @State ile Identifiable yapıları kullanmaktır.

Üçüncü sorun—deinit temizliği eksikliği. @StateObject, view’ın tüm yaşam döngüsü boyunca yaşar. Nesne zamanlayıcılar, Combine abonelikleri veya ağ istekleri oluşturursa, deinit bunları iptal etmelidir. Aksi takdirde, bellek sızıntıları ve ekran kapatıldıktan sonra arka plan çalışmasının devam etmesi kaçınılmazdır. Her zaman bir Combine Cancellable deposu kullanın veya deinit içinde zamanlayıcıları geçersiz kılın.

Sıkça Sorulan Sorular

@StateObject SwiftUI’da ne zaman tanıtıldı?

@StateObject, WWDC 2020’de SwiftUI 2.0’a iOS 14, macOS 11, watchOS 7 ve tvOS 14 ile birlikte eklendi. Bundan önce, @ObservedObject ObservableObject ile çalışmanın tek yoluydu ve bu da sık sık veri kaybı hatalarına yol açıyordu.

@StateObject isteğe bağlı olabilir mi?

Hayır, @StateObject Optional türlerini desteklemez. Nesne bildirim sırasında başlatılmalıdır. İsteğe bağlı bir nesneye ihtiyacınız varsa, isteğe bağlı bir türle @ObservedObject veya @EnvironmentObject kullanın.

@StateObject’in yalnızca bir kez oluşturulduğunu nasıl doğrularız?

ObservableObject’in başlatıcısına ve deinit’ine print(#function) ekleyin. Render işlemlerinde init çağrılmazsa—@StateObject doğru çalışıyordur. Init her çağrıldığında—@ObservedObject’i @StateObject ile değiştirin.

@StateObject, UIHostingController aracılığıyla UIKit ile kullanılabilir mi?

Evet, @StateObject, UIHostingController aracılığıyla UIKit’e gömülü SwiftUI view’larında çalışır. Nesne yaşam döngüsü, UIViewController’a değil, SwiftUI view’ına bağlıdır. SwiftUI view değiştirilirse, @StateObject yok edilir.

Hangisi daha iyi: büyük ViewModel’li tek @StateObject mi yoksa birkaç küçük mü?

Ayrı sorumluluklara sahip birkaç küçük @StateObject daha iyidir. Bu, test edilebilirliği, yeniden kullanılabilirliği ve performansı artırır—bir nesne değiştiğinde, tüm view değil, arayüzün yalnızca abone olunan kısımları yeniden çizilir.

Özet

  • @StateObject — view’da ObservableObject oluşturmak ve sahiplenmek için Property Wrapper
  • Tek örnek — sonraki body render işlemlerinde nesne yeniden oluşturulmaz
  • Gerçeğin kaynağı — kök view’daki @StateObject, hiyerarşi için veri kararlılığını garanti eder
  • Seçim kuralı — @StateObject oluşturma için, @ObservedObject hazır nesne alma için
  • Başlatma — @StateObject’teki parametreler bir kez hesaplanır, güncellemeler izlenmez
  • Deinit — ObservableObject’in deinit’inde zamanlayıcıların ve aboneliklerin zorunlu temizliği
  • iOS 14+ — @StateObject, iOS 14, macOS 11, watchOS 7, tvOS 14’ten itibaren kullanılabilir

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.

Projeyi tartış

Ayrıca okuyun