@StateObject: шта је то, креирање и управљање ObservableObject

Аутор: IT Sectr Објављено: 2026-06-26 Време читања: 9 мин

@StateObject је property wrapper у SwiftUI-ју који креира и поседује инстанцу ObservableObject током целог животног циклуса View-а. Када се View први пут појави на екрану, @StateObject иницијализује објекат и чува га док View не буде уклоњено из меморије. Ово гарантује да се подаци неће ресетовати приликом поновне изградње интерфејса — на пример, при промени теме или ажурирању родитељског View-а. Према Apple Developer Documentation (2025), @StateObject треба користити као главни извор истине (source of truth) за ObservableObject у хијерархији SwiftUI-ја, док подређена View добијају већ креирани објекат путем @ObservedObject или @EnvironmentObject.

Главне тачке

  • @StateObject — property wrapper за креирање и поседовање ObservableObject унутар View-а.
  • Једнократно креирање — објекат се иницијализује једном током живота View-а и не поново се ствара при преправкама.
  • Source of truth — @StateObject је извор истине у хијерархији, за разлику од @ObservedObject.
  • Животни циклус — објекат живи док View постоји у меморији и уништава се заједно са њим.
  • Иницијализација — @StateObject захтева почетну вредност при креирању, обично путем init-а са параметрима.

Шта је @StateObject у SwiftUI-ју

@StateObject је property wrapper представљен у iOS 14 који омогућава View-у да креира и поседује инстанцу класе која је у складу са протоколом ObservableObject. За разлику од @State-а који ради са вредносним типовима (структурама), @StateObject је намењен референтним типовима — класама које могу обавештавати SwiftUI о променама својих својстава.

Када View користи @StateObject var viewModel: MyViewModel, SwiftUI аутоматски креира инстанцу MyViewModel при првом приказивању View-а и чува је у посебном складишту оквира. При сваком ажурирању View-а (на пример, при промени родитељског стања), SwiftUI не поново ствара објекат — користи постојећу инстанцу док View не буде уклоњено из хијерархије.

Према Apple WWDC Session 10137 (2024), @StateObject решава проблем губитка података при поновној изградњи View-а који је постојао у iOS 13, када су програмери морали да креирају ObservableObject у родитељском View-у и прослеђују га кроз иницијализатор. То је доводило до дуплирања кода и ризика од случајног поновног стварања објекта.

swift
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("Број: \(viewModel.count)")
            Button("Увећај", action: viewModel.increment)
        }
    }
}

Како ради @StateObject

Механизам @StateObject се заснива на интеграцији SwiftUI-ја са Combine оквиром. Када ObservableObject означи своја својства атрибутом @Published, SwiftUI се аутоматски претплаћује на промене путем publisher-а уграђеног у протокол ObservableObject. При промени објављеног својства, објекат шаље сигнал путем objectWillChange publisher-а, што покреће поновно цртање свих View-а која посматрају овај објекат.

SwiftUI чува инстанцу ObservableObject у посебном складишту везаном за одређену инстанцу View-а. Ово складиште се креира једном при првом рендеровању и постоји до уништења View-а. Управо зато @StateObject гарантује стабилност референце на објекат — SwiftUI аутоматски управља меморијом, не ослањајући се на иницијализатор View-а.

Према objc.io — Thinking in SwiftUI (2025), унутрашња имплементација @StateObject користи механизам сличан @State-у, али за референтне типове: SwiftUI креира boxing омотач око објекта и управља његовим животним циклусом путем сопственог алокатора, оптимизованог за честе преправке хијерархије View-а.

Животни циклус @StateObject

  • Креирање — при првом појављивању View-а на екрану, SwiftUI позива иницијализатор објекта и чува референцу.
  • Преправка — при ажурирању родитељског View-а, објекат се не поново ствара, користи се постојећа инстанца.
  • Уништење — када View напусти екран и буде уклоњено из хијерархије, SwiftUI позива deinit објекта.

@StateObject vs @ObservedObject: кључне разлике

Главна разлика између @StateObject и @ObservedObject је у томе ко поседује објекат. @StateObject креира и чува објекат — он је власник. @ObservedObject само посматра објекат који је креиран негде другде и прослеђен кроз иницијализатор или својство.

Карактеристика@StateObject@ObservedObject
ВласништвоКреира и поседује објекатСамо посматра
ИницијализацијаУнутар View-а путем init/defaultСпоља, прослеђује се кроз параметар
Животни циклусВезан за животни циклус View-аНије контролисан од стране View-а
Поновно стварањеНе ствара се поново при ажурирањуМоже бити замењен споља
iOS верзијаiOS 14+iOS 13+

Правило је једноставно: ако View креира ObservableObject — користи @StateObject. Ако View само прима већ готов објекат од родитеља — користи @ObservedObject. Кршење овог правила доводи или до губитка података (ако користите @ObservedObject за поседовање), или до прекомерног креирања објеката (ако користите @StateObject за посматрање).

Када користити @StateObject

@StateObject треба користити у оним View-има која су извор истине за одређени скуп података. Типични сценарији укључују екране са сопственим view model-ом, коренске екране навигационих стекова и модалне презентације које управљају сопственим стањем.

  • Екран са view model-ом — сваки екран који управља сопственим подацима и логиком треба да креира свој view model путем @StateObject.
  • Коренски View — у хијерархији NavigationStack или TabView, коренски елемент креира податке, а подређени их добијају путем @ObservedObject.
  • Модални прозори — .sheet и .fullScreenCover често захтевају сопствени @StateObject за управљање формом или процесом.
  • Листа са уређивањем — сваки ред листе који садржи формулар за уређивање треба да има сопствени @StateObject.
swift
struct ProfileView: View {
    @StateObject var viewModel = ProfileViewModel()
    
    var body: some View {
        NavigationStack {
            Form {
                TextField("Name", text: $viewModel.name)
                TextField("Email", text: $viewModel.email)
                Button("Сачувај") {
                    viewModel.saveProfile()
                }
            }
            .navigationTitle("Profile")
        }
    }
}

Иницијализација @StateObject са параметрима

Иницијализација @StateObject са параметрима захтева употребу посебне синтаксе, јер SwiftUI самостално управља креирањем објекта. Не можете једноставно проследити параметре у иницијализатор — потребно је користити escaping затварање или посебан метод креирања.

Према Swift by Sundell (2024), најчистији начин је коришћење фабричког метода или затварања које ће SwiftUI позвати при првом креирању објекта. Алтернативни приступ — иницијализовати ObservableObject у родитељском View-у и проследити га путем @StateObject користећи стандардни иницијализатор.

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

Важно је запамтити да иницијализатор View-а са @StateObject мора користити доњу црту испред имена својства (_viewModel) за приступ самом property wrapper-у, а не његовој вредности. Ово је стандардни Swift образац за рад са property wrapper-има у иницијализаторима.

Типичне грешке са @StateObject

Најчешћа грешка је коришћење @ObservedObject уместо @StateObject за View које треба да поседује објекат. У овом случају, при свакој преправци родитеља, објекат ће бити поново креиран, што доводи до губитка свих прикупљених података. Ова грешка је посебно подмукла у сложеним хијерархијама са NavigationStack или TabView.

  • Губитак података при навигацији — ако подређени екран користи @ObservedObject за сопствени view model, при повратку и поновном отварању подаци ће се ресетовати.
  • Цурење меморије — креирање @StateObject у родитељском View-у које се никада не уклања може довести до акумулације објеката, ако сваки подређени екран такође креира @StateObject без контроле.
  • Дуплирање објеката — прослеђивање једног ObservableObject-а више @StateObject-а у различитим View-има креира неколико независних инстанци које се не синхронизују међусобно.

Да бисте избегли ове проблеме, следите једноставно правило: један @StateObject по једном извору истине. Ако подаци треба да буду заједнички за више екрана — креирајте @StateObject једном у коренском View-у и прослеђујте га путем @ObservedObject или @EnvironmentObject подређеним елементима.

swift
// ❌ Погрешно: @ObservedObject за поседовање објекта
struct BadView: View {
    @ObservedObject var vm = ViewModel() // биће поново креиран при сваком ажурирању!
}

// ✅ Исправно: @StateObject за поседовање
struct GoodView: View {
    @StateObject var vm = ViewModel() // креиран једном за животни век View-а
}

Често постављана питања

Која је разлика између @StateObject и @State?

@State ради са вредносним типовима (структуре, стрингови, бројеви) и чува вредност директно у SwiftUI складишту. @StateObject ради са референтним типовима — класама у складу са ObservableObject. @State је погодан за једноставна локална стања, @StateObject — за сложене објекте са логиком и објављеним својствима.

Може ли се @StateObject користити у iOS 13?

Не, @StateObject је доступан само од iOS 14 и новије. За iOS 13 користите @ObservedObject и креирајте ObservableObject у родитељском View-у путем @State са ручним управљањем животним циклусом. Алтернатива — користите @State са struct уместо class за податке који не захтевају референтну семантику.

Шта се дешава ако користим @StateObject у подређеном View-у у које се објекат прослеђује од родитеља?

Подређени View ће креирати своју сопствену копију ObservableObject-а, потпуно независну од родитељске. Промене у једној неће се одразити на другу. Ово је готово увек грешка: користите @ObservedObject за пријем објекта од родитеља, а @StateObject само за креирање новог објекта унутар View-а.

Када се уништава објекат креиран путем @StateObject?

Објекат се уништава када View које га је креирало буде потпуно уклоњено из SwiftUI хијерархије. За екран у NavigationStack-у то се дешава при pop-у са навигационог стека. За модални прозор — при његовом затварању. За TabView — при пребацивању картице, ако View није кеширано.

Како проследити параметре у @StateObject при иницијализацији?

Користите прилагођени init са приступом property wrapper-у кроз доњу црту: _viewModel = StateObject(wrappedValue: MyViewModel(param: value)). Овај образац омогућава прослеђивање било којих параметара ObservableObject-у, задржавајући притом гаранцију јединственог креирања објекта током живота View-а.

Закључак

  • @StateObject — property wrapper за креирање и поседовање ObservableObject унутар View-а, доступан од iOS 14.
  • Гаранција јединственог креирања — објекат се иницијализује једном и не поново се ствара при преправци View-а.
  • Source of truth — @StateObject је извор истине, а @ObservedObject само посматрач.
  • Животни циклус — објекат живи док View постоји у SwiftUI хијерархији и уништава се при напуштању исте.
  • Иницијализација са параметрима — захтева приступ property wrapper-у путем _viewModel и StateObject(wrappedValue:).
  • Грешка власништва — коришћење @ObservedObject за креирање објекта доводи до губитка података при преправци.
  • Један објекат — један @StateObject — за заједничке податке креирајте @StateObject у коренском View-у и прослеђујте подређенима путем @ObservedObject.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође