@EnvironmentObject, SwiftUI'de, başlatıcıda açıkça iletmeden ObservableObject'i tüm görünüm hiyerarşisi boyunca otomatik olarak ileten bir property wrapper'dır. Alt görünüm, sadece bir özellik bildirerek ortam nesnesine erişim sağlarken, üst görünüm onu .environmentObject() yöntemi aracılığıyla sağlar. Apple Developer Documentation (2025)'ye göre SwiftUI, ortam düzeyinde bağımlılık enjeksiyonu mekanizması kullanarak ara görünümlerin başlatıcıları aracılığıyla veri iletme ihtiyacını ortadan kaldırır. @EnvironmentObject, kimlik doğrulama modelleri, alışveriş sepetleri veya genel ayarlar gibi bir uygulamanın birçok ekranı tarafından gereken nesneler için özellikle kullanışlıdır.
Önemli Noktalar
.environmentObject() yöntemiyle gerçekleştirilir — nesne tüm alt öğeler için kullanılabilir hale gelir@Environment aracılığıyla çalışmaya devam eder@EnvironmentObject, SwiftUI framework'ünde bildirilen ve bir görünümün ortamda depolanan bir nesneye erişmesini sağlayan bir property wrapper'dır. @State veya @StateObject'in aksine, @EnvironmentObject bir nesne oluşturmaz — yalnızca görünüm hiyerarşisindeki atalardan biri tarafından sağlanan mevcut bir örneği okur.
Mekanizma, SwiftUI ortamına dayanır — kök görünümden tüm alt görünümlere iletilen örtük bir sözlük. Bir üst görünüm .environmentObject(someObject) yöntemini çağırdığında, SwiftUI ortama someObject'e bir referans yerleştirir. Alt ağaçtaki herhangi bir görünüm @EnvironmentObject var model: ViewModel bildirebilir ve aynı örneği alabilir.
Apple WWDC 2021 oturumu “Demystify SwiftUI”ye göre ortam, performans kaybı olmadan derin bir hiyerarşi aracılığıyla veri iletmek için optimize edilmiştir — nesneye erişim, tür tabanlı arama yoluyla O(1)'de gerçekleşir. Bu, karmaşıklığın hiyerarşi derinliğiyle doğrusal olarak arttığı başlatıcılar aracılığıyla manuel iletimin tersidir.
Uygulamanın farklı seviyelerinde gereken global durum için @EnvironmentObject kullanın. Tipik adaylar kimlik doğrulama modelleri, navigasyon yöneticileri, alışveriş sepetleri ve ağ veri sağlayıcılarıdır.
@EnvironmentObject, ortam tabanlı bağımlılık enjeksiyonu adı verilen bir SwiftUI mekanizmasını kullanır. SwiftUI hiyerarşiyi render ettiğinde, her seviyede okuma ve yazma için erişilebilen dahili bir sözlük EnvironmentValues tutar. @EnvironmentObject property wrapper, değişikliklere abone olmak için ObservableObject protokolünden objectWillChange'i kullanarak bu sözlükten türe göre okur.
Süreç üç adımdan oluşur. Birincisi, hiyerarşide bir yerde ObservableObject oluşturmak, tipik olarak bir üst görünümde @StateObject veya @ObservedObject aracılığıyla. İkincisi, bu görünümde .environmentObject(object) çağırmak, bu da nesneyi ortama yerleştirir. Üçüncüsü, alt görünümlerde @EnvironmentObject bildirmek, bunlar otomatik olarak aynı örneği alır ve abone olur.
SwiftUI, nesne içindeki herhangi bir @Published özelliği değiştiğinde, bu türle @EnvironmentObject bildiren tüm görünümlerin yeniden render edileceğini garanti eder. Donny Wals (2024) tarafından yazılan bir makaleye göre, abonelik mekanizması @ObservedObject ile aynıdır — fark yalnızca örneği elde etme şeklindedir, güncelleme mekanizmasında değildir.
Hiyerarşiyi, nesne mümkün olduğunca yüksekte sağlanacak şekilde tasarlayın — bu, kod tekrarı olmadan ona ihtiyaç duyan tüm görünümler için erişim sağlar.
Her iki property wrapper — @EnvironmentObject ve @ObservedObject — bir ObservableObject'e abone olur ve değişikliklerde görünümü yeniden render eder. Temel fark, nesneyi elde etme şeklidir. @ObservedObject, görünüm başlatıcısı aracılığıyla örneğin açıkça iletilmesini gerektirirken, @EnvironmentObject onu ortamdan otomatik olarak alır.
Üç seviyeli bir hiyerarşi düşünün: ParentView → MiddleView → ChildView. ChildView'ın bir UserSettings nesnesine ihtiyacı varsa, @ObservedObject kullanıldığında, MiddleView bu nesneyi kullanmasa bile onu MiddleView aracılığıyla iletmek gerekecektir:
struct MiddleView: View {
@ObservedObject var settings: UserSettings // only needed to pass down
var body: some View {
ChildView(settings: settings)
}
}
@EnvironmentObject ile MiddleView'ın nesnenin varlığından haberdar olması gerekmez:
struct MiddleView: View {
var body: some View {
ChildView()
}
}
struct ChildView: View {
@EnvironmentObject var settings: UserSettings
var body: some View {
Text(settings.username)
}
}
Swift by Sundell (2024)'e göre @EnvironmentObject, bir nesnenin hiyerarşinin birden çok seviyesinde ihtiyaç duyulduğunda tercih edilirken, @ObservedObject nesne doğrudan bir üstten tek bir doğrudan alt öğeye iletildiğinde daha iyidir. Yerel, tek seferlik iletimler için @ObservedObject'i ve global bağımlılıklar için @EnvironmentObject'i seçin.
@Environment ve @EnvironmentObject her ikisi de SwiftUI ortamından veri okur, ancak farklı kaynaklarla çalışır. @Environment, EnvironmentValues'den yerleşik veya özel değerleri okur — bunlar basit verilerdir: renkler, yazı tipleri, boyutlar, takvim, layoutDirection. @EnvironmentObject, ObservableObject'e uyan referans türlerini okur.
Temel fark güncelleme mekanizmasıdır. @Environment, bireysel değer düzeyinde publish-subscribe kullanır: ortam değiştiğinde, yalnızca bu değeri okuyan görünümler yeniden render edilir. @EnvironmentObject, ObservableObject'in objectWillChange'ine abone olur, bu da hangi belirli özelliğin değiştiğine bakılmaksızın bu türe abone olan tüm görünümlerin yeniden render edilmesine neden olabilir.
Hacking with Swift (Paul Hudson, 2025)'e göre @Environment, yapılandırma parametreleri için uygundur: renk şeması, dinamik yazı tipi boyutu, cihaz yönü. @EnvironmentObject, iş mantığı ve durum içindir: veri modelleri, servisler, yöneticiler. Statik veya nadiren değişen parametreler için @Environment'ı ve reaktivite gerektiren dinamik veriler için @EnvironmentObject'i kullanın.
Pratikte, bu iki mekanizma sıklıkla birleştirilir: @EnvironmentObject veri sağlar, @Environment ise görüntüleme bağlamını sağlar.
En yaygın hata, erişim sırasında ortamda nesne eksikliğidir. Bir görünüm @EnvironmentObject var model: ViewModel bildirir, ancak hiçbir ata .environmentObject(model) çağırmazsa, SwiftUI şu mesajla bir fatal error fırlatır: “ViewModel türünde ObservableObject bulunamadı.” Bu, derleme zamanında değil render zamanında olur, bu nedenle hata yalnızca çalışma zamanında ortaya çıkabilir.
İkinci yaygın sorun, aynı türün birden çok örneğidir. SwiftUI, ortamda arama için anahtar olarak nesne türünü kullanır. İki farklı ata, .environmentObject aracılığıyla ViewModel'in farklı örneklerini sağladıysa, alt görünüm hiyerarşide en yakın olanı alır, bu da beklenmeyen davranışa yol açabilir. Çözüm, her türün ortamda tam olarak bir kez görüneceği şekilde tasarlamaktır.
Üçüncü hata, yalnızca bir veya iki görünümün ihtiyaç duyduğu veriler için @EnvironmentObject'in aşırı kullanımıdır. Bu durumda, başlatıcı aracılığıyla açık iletimli @ObservedObject daha şeffaf bir veri akışı sağlar ve test etmeyi basitleştirir. Point-Free (2025)'e göre, ortamda aşırı sayıda nesne, görünüm bağımlılıklarını anlamayı zorlaştırır ve kodu daha az öngörülebilir hale getirir.
Her @EnvironmentObject'in hiyerarşinin doğru seviyesinde sağlandığını kontrol edin ve kritik nesneler için onAppear'da yedek kontroller ekleyerek eksiklikleri erken yakalayın.
Global kimlik doğrulama durumuna sahip bir uygulamanın tam örneğini düşünün. Kullanıcı giriş durumunu depolayan bir ObservableObject AuthManager oluşturacağız ve bunu @EnvironmentObject aracılığıyla tüm ekranlara sağlayacağız:
import SwiftUI
import Combine
class AuthManager: ObservableObject {
@Published var isLoggedIn = false
@Published var username: String = ""
func login(user: String) {
username = user
isLoggedIn = true
}
func logout() {
username = ""
isLoggedIn = false
}
}
Kök görünüm, AuthManager'i ortam aracılığıyla sağlar:
@main
struct MyApp: App {
@StateObject private var authManager = AuthManager()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(authManager)
}
}
}
Bir alt görünüm, açık iletim olmadan AuthManager'i alır:
struct ProfileView: View {
@EnvironmentObject var authManager: AuthManager
var body: some View {
VStack {
if authManager.isLoggedIn {
Text("Hello, \(authManager.username)")
Button("Log Out") {
authManager.logout()
}
} else {
Button("Log In") {
authManager.login(user: "user")
}
}
}
}
}
Üçüncü örnek, birden çok ObservableObject ve @EnvironmentObject ile @Environment'in birleşimini içerir. Uygulamanın alışveriş sepeti için bir CartManager ve renk şeması için bir ThemeManager kullandığını varsayalım. Her ikisi de üst düzeyde sağlanır ve başlatıcılar aracılığıyla iletilmeden herhangi bir ekranda kullanılabilir. Bu, özellikle derinlemesine iç içe ekranlar veya modal sunumlarda kullanışlıdır, çünkü yapıcılar aracılığıyla veri iletimi teknik olarak zordur.
Sıkça Sorulan Sorular
@ObservedObject, görünüm başlatıcısı aracılığıyla örneğin açıkça iletilmesini gerektirirken, @EnvironmentObject nesneyi SwiftUI ortamından otomatik olarak alır. @EnvironmentObject, hiyerarşinin birden çok seviyesinde ihtiyaç duyulan veriler için uygunken, @ObservedObject üst ve alt arasında doğrudan iletim için tercih edilir.
SwiftUI çalışma zamanında bir fatal error fırlatacaktır: “X türünde ObservableObject bulunamadı.” Hata, @EnvironmentObject bildiren görünümün render edilmesi sırasında, hiçbir ata bu türden bir nesneyle .environmentObject() çağırmamışsa oluşur. Derleyici bu durum hakkında uyarı vermez.
Evet, @EnvironmentObject iOS 13.0, macOS 10.15, tvOS 13.0 ve watchOS 6.0'dan beri kullanılabilir. Apple'ın 2019'da SwiftUI ile birlikte tanıttığı ilk property wrapper'lardan biridir ve @Observable makrosu dahil iOS 17 ve 18 dahil sonraki tüm sürümlerde çalışır.
Nesne sayısı sınırsızdır — her tür benzersiz bir anahtar görevi görür. AuthManager, CartManager, NavigationManager ve diğer servisleri her biri için ayrı ayrı .environmentObject() çağırarak iletebilirsiniz. Ortamda aynı türden iki nesnenin olmaması önemlidir — bu, tanımsız davranışa yol açar.
Testlerde, bir ObservableObject örneği oluşturun ve bunu bir Preview Provider veya XCTest'te .environmentObject(obj) aracılığıyla iletin. Görünüm enjeksiyonunun birim testleri için, somut bir sınıf yerine bir protokol kullanmak uygundur — bu, gerçek hiyerarşiyi değiştirmeden bağımlılıkların mock nesnelerle değiştirilmesine olanak tanır.
Özet
.environmentObject() aracılığıyla ortama yerleştirilir ve türe göre alınırAnahtar 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