@StateObject: bu nədir, @ObservedObject-dən fərqi və nümunələr

Müəllif: IT Sectr Dərc olunub: 2026-06-19 Oxuma vaxtı: 7 dəq

@StateObject SwiftUI-də ObservableObject nümunəsini birbaşa view-də yaratmaq və sahib olmaq üçün Property Wrapper-dir. SwiftUI təmin edir ki, obyekt görünüşün həyat dövrü üçün bir dəfə başladılır və təkrar renderlər zamanı yenidən yaradılmır. Apple Developer Documentation (2025)-yə görə, @StateObject məlumat mənbəyi yaradan kök view-lər üçün tövsiyə olunur. @StateObject SwiftUI iyerarxiyasında ObservableObject-ə sahib olmaq üçün düzgün seçimdir.

Əsas məqamlar

  • @StateObject — view-də ObservableObject yaratmaq və sahib olmaq üçün Property Wrapper
  • Tək nümunə — obyekt bir dəfə yaradılır və renderlər zamanı yenidən yaradılmır
  • Həqiqət mənbəyi — @StateObject bütün iyerarxiya üçün məlumat sabitliyini təmin edir
  • @ObservedObject-dən fərqi — @ObservedObject obyektə sahib deyil və onu itirə bilər
  • Kök view-lər — @StateObject obyekti yaradan view-də istifadə olunur

SwiftUI-də @StateObject nədir?

@StateObject SwiftUI 2.0-da (iOS 14) ortaya çıxan, @ObservedObject və @State-in imkanlarını birləşdirən Property Wrapper-dir. @ObservedObject kimi, ObservableObject-dəki dəyişikliklərə abunə olur. @State kimi, məlumatların view strukturunun təkrar başlatmalarından sağ çıxmasını təmin edir. @StateObject obyekti view ekranda ilk dəfə görünəndə bir dəfə yaradır və SwiftUI yığınında saxlayır.

@StateObject yaranmazdan əvvəl tərtibatçılar bütün ObservableObject-lər üçün, o cümlədən view-lərdə yaradılanlar üçün @ObservedObject istifadə edirdilər. Bu, valideyn view yeniləndikdə, view strukturunun yenidən yaradılması və @ObservedObject nümunəsini də özü ilə aparması səbəbindən tez-tez məlumat itkisinə səbəb olurdu. @StateObject bu problemi sabitlik zəmanəti əlavə edərək həll etdi.

Əsas qayda: @StateObject standart başlatıcıda (let model = ViewModel()) obyekti yaradan view-də tətbiq olunur. Bu obyekti alan uşaq view-lər @ObservedObject istifadə edir. Belə bölgü bütün iyerarxiyada yeganə həqiqət mənbəyini təmin edir.

@StateObject-in həyat dövrü

SwiftUI @StateObject-in həyat dövrünü @State-ə bənzər saxlama meneceri vasitəsilə idarə edir. View ilk dəfə görünəndə SwiftUI obyekt üçün yaddaş ayırır və onu davamlı sahədə saxlayır. Təkrar renderlər zamanı (body çağırışı) obyekt yenidən yaradılmır — mövcud nümunə istifadə olunur. Obyekt view iyerarxiyada olduğu müddətcə yaşayır.

View iyerarxiyadan silindikdə, SwiftUI @StateObject-i məhv edir, deinit-i çağırır. View iyerarxiyaya yenidən əlavə edildikdə yeni nümunə yaradılır. Bunu layihələşdirərkən nəzərə almaq vacibdir: view silinmələri arasında məlumatları saxlamaq lazımdırsa, davamlılıq üçün xidmət qatından (sinqleton və ya DI) və ya @AppStorage-dən istifadə edin.

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() }
    }
}

Nümunədə TimerViewModel @StateObject vasitəsilə yaradılır və TimerView ekranda olduğu müddətcə yaşayır. Timer onAppear-da başlayır və deinit-də dayanır. Əgər @ObservedObject istifadə olunsaydı, hər TimerView renderində saniyələri = 0 olan yeni TimerViewModel yaradılacaq və timer heç vaxt düzgün işləməyəcəkdi. @StateObject təmin edir ki, viewModel yeganə və sabitdir.

@StateObject vs @ObservedObject: müqayisə

@StateObject və @ObservedObject arasında seçim obyektə kimin sahib olmasından asılıdır. View obyekti yaradırsa — @StateObject. View hazır obyekt alırsa — @ObservedObject. Bu qayda o qədər vacibdir ki, Xcode başlatıcı vasitəsilə obyekt alan uşaq view-də @StateObject istifadə edildikdə xəbərdarlıq göstərir.

VəziyyətTövsiyə olunan wrapper
View ViewModel() vasitəsilə model yaradır@StateObject
View modeli valideyndən alır@ObservedObject
Model bir view-də istifadə olunur@StateObject
Model Environment vasitəsilə ötürülür@EnvironmentObject
Model ön baxış üçün lazımdır@ObservedObject + mock

Təcrübədə layihənin əvvəlində tez-tez kök view-də @StateObject və bütün uşaq view-lərdə @ObservedObject istifadə olunur. Tətbiq böyüdükcə iyerarxiyanı sadələşdirmək üçün @StateObject-in bir hissəsi @EnvironmentObject ilə əvəz edilə bilər. Lakin @StateObject öz məntiqi olan modul ekranlar üçün ən yaxşı seçim olaraq qalır.

@StateObject istifadə nümunələri

Birinci nümunə — MVVM @StateObject ilə. ViewModel ObservableObject kimi view-də @StateObject vasitəsilə yaradılır. ViewModel @Published xassələri və biznes məntiqini ehtiva edir. View dəyişikliklərə abunə olur və interfeysi yeniləyir. Bu yanaşma test edilə bilən izolyasiya verir: ViewModel birbaşa nümunə yaradaraq UI olmadan test edilə bilər.

İkinci nümunə — @StateObject asılılıqlarla. ViewModel xidmətlər tələb edirsə, parametrlərlə başlatmadan istifadə edin. Məsələn, @StateObject var viewModel = UserViewModel(api: APIClient.shared). Bununla belə, diqqətli olun: parametrlər hər body renderində hesablanır, lakin obyekt yalnız bir dəfə yaradılır. SwiftUI @StateObject-in sonrakı başlatmalarına məhəl qoymur.

Üçüncü nümunə — iç-içə @StateObject. SwiftUI-də bir view-də bir neçə @StateObject ola bilər, lakin bu nadir hallarda əsaslandırılır. Adətən bir @StateObject view-in bütün məlumat dəsti üçün cavabdehdir. Məntiq çox mürəkkəbləşərsə, onu bir @StateObject daxilində @ObservedObject xidmətlərin kompozisiyasına bölün.

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

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

Nümunədə AppView iki @StateObject yaradır: naviqasiyanı idarə etmək üçün NavigationRouter və autentifikasiya üçün AuthViewModel. Hər iki obyekt environmentObject vasitəsilə Environment-ə daxil edilir. İstənilən uşaq view onlara başlatma zəncirindən keçmədən @EnvironmentObject vasitəsilə daxil ola bilər.

@StateObject və parametrlərlə başlatma

@StateObject istənilən parametrlərlə başlatmanı dəstəkləyir, lakin vacib bir xüsusiyyətlə: başlatıcı yalnız bir dəfə çağırılır. Body-nin təkrar renderlərində parametrlərin yeni dəyəri nəzərə alınmır. Bu o deməkdir ki, @State var id: Int = 5-i @StateObject var vm = ViewModel(id: id)-yə ötürsəniz, id dəyişdikdə ViewModel yeni dəyər almayacaq.

Bu problemi həll etmək üçün sinxronizasiya üçün onReceive və ya onAppear istifadə edin. Combine vasitəsilə ViewModel daxilində parametr dəyişikliklərinə abunə olun və ya view səviyyəsində .onChange(of:) metodu vasitəsilə parametrləri ötürün. Alternativ — obyekt xarici dəyişikliklərə dinamik reaksiya verməlidirsə, @StateObject əvəzinə @ObservedObject istifadə edin.

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

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

Düzgün yanaşma: DetailView itemId-ni let xassəsi kimi alır (struktur başlatıcısı vasitəsilə ötürülür), @StateObject isə parametrsiz DetailViewModel yaradır. onAppear-da ötürülən ID üçün məlumatları yükləyən load(id:) metodu çağırılır. Bu təmin edir ki, ViewModel @StateObject mexanizmi ilə yaradılıb, lakin məlumatlar hər view görünəndə cari ID ilə yüklənir.

@StateObject ilə tipik səhvlər

Əsas səhv — uşaq view-lərdə @StateObject istifadə etməkdir ki, onlar obyekti valideyndən alırlar. ParentView @StateObject model yaradırsa və ChildView @StateObject var model: ModelType (standart parametrlə) elan edirsə, ChildView öz müstəqil nümunəsini yaradacaq. Valideyn və uşaq obyektləri əlaqəli olmayacaq və birindəki dəyişikliklər digərində əks olunmayacaq.

İkinci səhv — @StateObject-i List və ya ForEach-də yerləşdirmək. Siyahının hər bir elementi öz @StateObject-ni yaradır ki, bu da çoxsaylı müstəqil nümunələrə gətirib çıxarır. Siyahılar üçün bütün elementlərə bir ObservableObject-i @ObservedObject vasitəsilə ötürmək və ya List daxilində @State ilə Identifiable strukturlardan istifadə etmək düzgündür.

Üçüncü problem — deinit təmizləməsinin olmaması. @StateObject view-in bütün həyat dövrü boyu yaşayır. Obyekt taymerlər, Combine abunəlikləri və ya şəbəkə sorğuları yaradırsa, deinit onları ləğv etməlidir. Əks halda yaddaş sızmaları və ekran bağlandıqdan sonra fon işinin davam etməsi qaçılmazdır. Həmişə Combine Cancellable store və ya deinit-də taymerlərin invalidate-dən istifadə edin.

Tez-tez verilən suallar

@StateObject SwiftUI-də nə vaxt ortaya çıxdı?

@StateObject SwiftUI 2.0-da WWDC 2020-də iOS 14, macOS 11, watchOS 7 və tvOS 14 ilə birlikdə əlavə edildi. Bundan əvvəl @ObservedObject ObservableObject ilə işləməyin yeganə yolu idi ki, bu da tez-tez məlumat itkisi ilə bağlı xətalara səbəb olurdu.

@StateObject isteğe bağlı (optional) ola bilərmi?

Xeyr, @StateObject Optional tiplərini dəstəkləmir. Obyekt elan zamanı başladılmalıdır. İsteğe bağlı obyekt lazımdırsa, isteğe bağlı tiplə @ObservedObject və ya @EnvironmentObject istifadə edin.

@StateObject-in yalnız bir dəfə yaradıldığını necə yoxlamaq olar?

ObservableObject-in başlatıcısına və deinit-inə print(#function) əlavə edin. Təkrar renderlərdə init çağırılmırsa — @StateObject düzgün işləyir. Init hər dəfə çağırılırsa — @ObservedObject-i @StateObject ilə əvəz edin.

@StateObject UIKit ilə UIHostingController vasitəsilə istifadə edilə bilərmi?

Bəli, @StateObject UIHostingController vasitəsilə UIKit-ə yerləşdirilmiş SwiftUI view-lərində işləyir. Obyektin həyat dövrü UIViewController-ə deyil, SwiftUI view-ə bağlıdır. SwiftUI view əvəz edilərsə, @StateObject məhv edilir.

Hansı daha yaxşıdır: böyük ViewModel ilə bir @StateObject yoxsa bir neçə kiçik?

Ayrılmış məsuliyyətli bir neçə kiçik @StateObject. Bu, test edilə bilərliyi, təkrar istifadəni və performansı yaxşılaşdırır — bir obyekt dəyişdikdə interfeysin yalnız abunə olunmuş hissələri yenidən çəkilir, bütün view yox.

Nəticə

  • @StateObject — view-də ObservableObject yaratmaq və sahib olmaq üçün Property Wrapper
  • Tək nümunə — obyekt body-nin təkrar renderlərində yenidən yaradılmır
  • Həqiqət mənbəyi — kök view-də @StateObject iyerarxiya üçün məlumat sabitliyini təmin edir
  • Seçim qaydası — @StateObject yaratmaq üçün, @ObservedObject hazır obyekt almaq üçün
  • Başlatma — @StateObject-də parametrlər bir dəfə hesablanır, yeniləmələr izlənilmir
  • Deinit — ObservableObject-in deinit-də taymerlərin və abunəliklərin məcburi təmizlənməsi
  • iOS 14+ — @StateObject iOS 14, macOS 11, watchOS 7, tvOS 14-dən etibarən mövcuddur

Aç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.

Layihəni müzakirə et

Həm də oxuyun