@EnvironmentObject — SwiftUI-də property wrapper-dır, ObservableObject-i açıq şəkildə initilizatora ötürmədən bütün view iyerarxiyası vasitəsilə avtomatik ötürür. Uşaq view şəkildə obyektə sadəcə xassə elan etməklə çevrə mühiti obyektinə çıxış əldə edir, valideyn isə onu .environmentObject() metodu ilə təmin edir. Apple Developer Documentation (2025) məlumatlarına görə, SwiftUI çevrə mühiti səviyyəsində asılılıq inyeksiyası mexanizmindən istifadə edir ki, bu da ara view konstruktorları vasitəsilə məlumatları ötürmək ehtiyacını aradan qaldırır. @EnvironmentObject xüsusilə tətbiqin bir çox ekranında tələb olunan obyektlər üçün faydalıdır — autentifikasiya modelləri, alış-veriş səbətləri və ya qlobal parametrlər.
Əsas məqamlar
.environmentObject() metodu ilə həyata keçirilir — obyekt bütün uşaq elementlər üçün əlçatan olur@Environment vasitəsilə işləməyə davam edir@EnvironmentObject — SwiftUI çərçivəsində elan edilmiş property wrapper-dır, view-ə çevrə mühitində saxlanılan obyektə çıxış imkanı verir. @State və ya @StateObject-dən fərqli olaraq, @EnvironmentObject obyekt yaratmır — o, yalnız view iyerarxiyasında əcdadlardan biri tərəfindən təmin edilmiş mövcud instansiyanı oxuyur.
İş mexanizmi SwiftUI çevrə mühitinə — kök view-dən bütün uşaqlara ötürülən qeyri-açıq lüğətə əsaslanır. Valideyn .environmentObject(someObject) metodunu çağırdıqda, SwiftUI someObject-ə istinadı çevrə mühitinə yerləşdirir. Alt ağacdakı istənilən view @EnvironmentObject var model: ViewModel elan edə və eyni instansiyanı əldə edə bilər.
Apple WWDC 2021 “Demystify SwiftUI” sessiyasına görə, çevrə mühiti dərin iyerarxiya vasitəsilə performans itkisi olmadan məlumat ötürmək üçün optimallaşdırılıb — obyektə giriş tip üzrə axtarış vasitəsilə O(1) ilə həyata keçirilir. Bu, mürəkkəbliyin iyerarxiya dərinliyi ilə xətti artdığı konstruktorlar vasitəsilə əl ilə ötürmədən fərqlənir.
Tətbiqin müxtəlif səviyyələrində tələb olunan qlobal vəziyyət üçün @EnvironmentObject istifadə edin. Tipik namizədlər — autentifikasiya modelləri, naviqasiya menecerləri, alış-veriş səbətləri və şəbəkə məlumat təminatçıları.
@EnvironmentObject SwiftUI-nin çevrə mühitinə əsaslanan asılılıq inyeksiyası adlı mexanizmindən istifadə edir. SwiftUI iyerarxiyanı render edərkən, hər səviyyədə oxunub yazıla bilən daxili EnvironmentValues lüğətini saxlayır. @EnvironmentObject property wrapper-i dəyişikliklərə abunə olmaq üçün ObservableObject protokolundan objectWillChange istifadə edərək bu lüğətdən obyekti tipinə görə oxuyur.
Proses üç addımdan ibarətdir. Birinci — iyerarxiyada haradasa ObservableObject yaratmaq, adətən valideyn view-də @StateObject və ya @ObservedObject vasitəsilə. İkinci — bu view-də .environmentObject(object) çağırmaq, obyekti çevrə mühitinə yerləşdirir. Üçüncü — uşaq view-lərdə @EnvironmentObject elan etmək, onlar avtomatik olaraq eyni instansiyanı alır və abunə olurlar.
SwiftUI zəmanət verir ki, obyekt daxilində istənilən @Published xassəsi hər dəfə dəyişdikdə, bu tiplə @EnvironmentObject elan etmiş bütün view-lər yenidən çəkiləcək. Donni Uolsa görə (Donny Wals, 2024), abunə mexanizmi @ObservedObject ilə eynidir — fərq yalnız instansiyanın əldə edilmə üsulundadır, yenilənmə mexanizmində deyil.
İyerarxiyanı elə qurun ki, obyekt mümkün qədər yüksəkdə təmin edilsin — bu, kodu təkrarlamadan ehtiyacı olan bütün view-lər üçün çıxışı təmin edəcək.
Hər iki property wrapper — @EnvironmentObject və @ObservedObject — ObservableObject-ə abunə olur və dəyişikliklər zamanı view-i yenidən çəkir. Əsas fərq obyektin əldə edilmə üsulundadır. @ObservedObject instansiyanın view-in initilizatoru vasitəsilə açıq ötürülməsini tələb edir, @EnvironmentObject isə onu avtomatik olaraq çevrə mühitindən alır.
Üç səviyyəli iyerarxiyanı nəzərdən keçirək: ParentView → MiddleView → ChildView. Əgər ChildView-ə UserSettings obyekti lazımdırsa, @ObservedObject istifadə edərkən onu MiddleView vasitəsilə ötürmək lazım gələcək, hətta MiddleView bu obyektdən istifadə etməsə belə:
struct MiddleView: View {
@ObservedObject var settings: UserSettings // yalnız aşağı ötürmək üçün lazımdır
var body: some View {
ChildView(settings: settings)
}
}
@EnvironmentObject ilə MiddleView obyektin mövcudluğu haqqında bilmək məcburiyyətində deyil:
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) məlumatlarına görə, @EnvironmentObject obyekt iyerarxiyanın bir neçə səviyyəsində tələb olunduqda üstünlük təşkil edir, @ObservedObject isə obyekt valideyndən yeganə birbaşa uşağa ötürüldükdə üstünlük təşkil edir. Yerli, birdəfəlik ötürmələr üçün @ObservedObject, qlobal asılılıqlar üçün isə @EnvironmentObject seçin.
@Environment və @EnvironmentObject — hər ikisi SwiftUI çevrə mühitindən məlumat oxuyur, lakin müxtəlif mənbələrlə işləyir. @Environment EnvironmentValues-dən daxili və ya xüsusi dəyərləri oxuyur — bunlar sadə məlumatlardır: rənglər, şriftlər, ölçülər, təqvim, layoutDirection. @EnvironmentObject ObservableObject-ə uyğun istinad tiplərini oxuyur.
Əsas fərq — yenilənmə mexanizmi. @Environment fərdi dəyərlər səviyyəsində publish-subscribe istifadə edir: çevrə mühiti dəyişdikdə yalnız həmin dəyəri oxuyan view-lər yenidən çəkilir. @EnvironmentObject ObservableObject-in objectWillChange-inə abunə olur ki, bu da hansı xassənin dəyişdiyindən asılı olmayaraq bu tipə abunə olmuş bütün view-lərin yenidən çəkilməsinə səbəb ola bilər.
Hacking with Swift (Paul Hudson, 2025) məlumatlarına görə, @Environment konfiqurasiya parametrləri üçün uyğundur: rəng sxemi, dinamik şrift ölçüsü, cihazın oriyentasiyası. @EnvironmentObject — biznes məntiqi və vəziyyət üçün: məlumat modelləri, xidmətlər, menecerlər. Statik və ya nadir dəyişən parametrlər üçün @Environment, reaktivlik tələb edən dinamik məlumatlar üçün isə @EnvironmentObject istifadə edin.
Praktikada bu iki mexanizm tez-tez birləşdirilir: @EnvironmentObject məlumat verir, @Environment isə göstərmə kontekstini təmin edir.
Ən geniş yayılmış səhv — ona müraciət edərkən çevrə mühitində obyektin olmaması. Əgər view @EnvironmentObject var model: ViewModel elan edibsə, lakin heç bir əcdad .environmentObject(model) çağırmayıbsa, SwiftUI “No ObservableObject of type ViewModel found” mesajı ilə fatal error atacaq. Bu, render mərhələsində baş verir, kompilasiya zamanı deyil, buna görə səhv yalnız icra zamanı üzə çıxa bilər.
İkinci geniş yayılmış problem — eyni tipin çoxsaylı instansiyaları. SwiftUI çevrə mühitində axtarış üçün obyektin tipindən açar olaraq istifadə edir. Əgər iki fərqli əcdad .environmentObject vasitəsilə ViewModel-in fərqli instansiyalarını təmin edibsə, uşaq view iyerarxiyada ən yaxın olanı alacaq ki, bu da gözlənilən davranışa səbəb ola bilər. Həll — hər tipin çevrə mühitində dəqiq bir dəfə olmasını təmin etmək.
Üçüncü səhv — yalnız bir-iki view-ə lazım olan məlumatlar üçün @EnvironmentObject-dən həddindən artıq istifadə. Bu halda @ObservedObject initilizator vasitƏlə açıq ötürmƉ ilə daha şəffaf məlumat axını təmin edir və testi asanlaşdırır. Point-Free (2025) məlumatlarına görə, çevrə mühitində həddindən artıq çox obyekt view asılılıqlarını anlamağı çətinləşdirir və kodu daha az proqnozlaşdırıla bilən edir.
Hər @EnvironmentObject-in iyerarxiyanın düzgün səviyyƉsindƉ təmin edildiyini yoxlayın və erkən mərhƉlƉdƉ çatışmazlığı aşkar etmək üçün kritik obyektlər üçün onAppear-də fallback yoxlamaları əlavə edin.
Qlobal autentifikasiya vəziyyəti olan tam tətbiq nümunəsini nəzərdən keçirək. İstifadəçinin giriş vəziyyətini saxlayan ObservableObject AuthManager yaradaq və onu @EnvironmentObject vasitəsilə bütün ekranlara təmin edək:
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 view AuthManager-i çevrə mühiti vasitəsilə təmin edir:
@main
struct MyApp: App {
@StateObject private var authManager = AuthManager()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(authManager)
}
}
}
Uşaq view AuthManager-i açıq ötürmə olmadan alır:
struct ProfileView: View {
@EnvironmentObject var authManager: AuthManager
var body: some View {
VStack {
if authManager.isLoggedIn {
Text("Hello, \(authManager.username)")
Button("Hesabdan çıx") {
authManager.logout()
}
} else {
Button("Daxil ol") {
authManager.login(user: "user")
}
}
}
}
}
Üçüncü nümunə — bir neçə ObservableObject və @EnvironmentObject ilə @Environment-in birləşdirilməsi. Tətbiqin alış-veriş səbəti üçün CartManager və rəng sxemi üçün ThemeManager istifadə etdiyini fərz edək. Hər ikisi yuxarı səviyyədə təmin edilir və initilizatorlar vasitƏlə ötürmədən istənilən ekranda əlçatandır. Bu, xüsusilə ekranların dərin yerləşdirilməsi və ya məlumatların konstruktor vasitƏlə ötürməsinin texniki cəhətdən çətin olduğu modal view-lərin istifadəsi zamanı rahatlıq yaradır.
Tez-tez verilən suallar
@ObservedObject instansiyanın view-in initilizatoru vasitəsilə açıq ötürülməsini tələb edir, @EnvironmentObject isə obyekti avtomatik olaraq SwiftUI çevrə mühitindən alır. @EnvironmentObject iyerarxiyanın bir neçə səviyyəsində tələb olunan məlumatlar üçün rahatdır, @ObservedObject isə valideyn və uşaq arasında birbaşa ötürmə üçün üstünlük təşkil edir.
SwiftUI icra zamanı fatal error atacaq: “No ObservableObject of type X found”. Səhv @EnvironmentObject elan etmiş view-in render edilməsi anında baş verir, əgər heç bir əcdad bu tipli obyektlə .environmentObject() çağırmayıbsa. Kompilator bu vəziyyət barədə xəbərdarlıq etməz.
Bəli, @EnvironmentObject iOS 13.0, macOS 10.15, tvOS 13.0 və watchOS 6.0-dan etibarən mövcuddur. Bu, Apple tərəfindən 2019-cu ildə SwiftUI ilə birlikdə təqdim edilmiş ilk property wrapper-lardan biridir və @Observable makrosu ilə iOS 17 və 18 də daxil olmaqla bütün sonrakı versiyalarda işləyir.
Obyektlərin sayı məhdud deyil — hər tip unikal açar rolunu oynayır. AuthManager, CartManager, NavigationManager və digər xidmətləri hər biri üçün ayrıca .environmentObject() çağırmaqla ötürmək olar. Çevrə mühitində eyni tipli iki obyektin olmaması vacibdir — bu, qeyri-müəyyən davranışa səbəb olar.
Testlərdə ObservableObject instansiyası yaradın və onu Preview Provider və ya XCTest-də .environmentObject(obj) vasitəsilə ötürün. View-in vahid testləri üçün konkret sinif əvəzinə protokol istifadə etmək rahatdır — bu, real iyerarxiyanı dəyişmədən asılılıqları mock-obyektlərlə əvəz etməyə imkan verir.
Nəticə
.environmentObject() metodu ilə çevrə mühitinə yerləşdirilir və tip üzrə çıxarılırAçar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun