@ObservedObject је Property Wrapper у SwiftUI за посматрање инстанце ObservableObject-а која је прослеђена споља. За разлику од @StateObject-а, @ObservedObject не креира објекат — он се претплаћује на промене већ постојећег. Према Apple Developer Documentation (2025), @ObservedObject се користи у изведеним view-овима којима је потребно праћење података који припадају родитељу. @ObservedObject обезбеђује реактивну везу без управљања животним циклусом објекта.
Главно
@ObservedObject је Property Wrapper који претплаћује view на промене ObservableObject-а. ObservableObject је протокол из Combine фрејмворка који захтева имплементацију objectWillChange publisher-а. Када се било које својство означено са @Published промени унутар ObservableObject-а, publisher шаље сигнал и SwiftUI поново исцртава све view-ове претплаћене преко @ObservedObject-а.
Главна особина @ObservedObject-а је недостатак власништва. View није одговоран за креирање или уништавање објекта. Објекат се креира у родитељском view-у (преко @StateObject-а) или се убацује преко @EnvironmentObject-а. Изведени view само посматра промене и прима ажурирања. Ако објекат буде замењен у родитељу, @ObservedObject ће се пребацити на нову инстанцу.
@ObservedObject је погодан за сценарије дељења података: модел корисника, заједничка подешавања, статус повезивања са сервером. Када више view-ова на различитим нивоима хијерархије треба да приказује исте податке, @ObservedObject у сваком view-у креира независне, али усаглашене претплате на један извор.
Разлика између @ObservedObject и @StateObject-а је једна од најчешћих тема питања на интервјуима за SwiftUI. Основно правило: @StateObject креира и поседује објекат, @ObservedObject посматра већ постојећи. Кршење овог правила доводи до неочекиваног губитка података или дупле иницијализације.
| Карактеристика | @StateObject | @ObservedObject |
|---|---|---|
| Креирање објекта | Да, при иницијализацији view-а | Не, прима готов |
| Власништво | Тренутни view | Родитељска компонента |
| Јединствена инстанца | Да, током целог животног циклуса | Не, може бити замењена |
| Поновно креирање при рендеровању | Не, чува се | Зависи од родитеља |
| Где користити | Корени view-власник | Изведени view-ови |
@StateObject гарантује да се објекат креира једном и преживљава поновне иницијализације структуре view-а. @ObservedObject прима објекат споља и поново се креира при свакој иницијализацији родитељске структуре. Ако родитељ користи @StateObject за објекат, изведени view-ови могу безбедно да примењују @ObservedObject — објекат ће бити јединствен у целој хијерархији.
Механизам праћења @ObservedObject-а заснива се на Combine-у и протоколу ObservableObject. При иницијализацији SwiftUI позива objectWillChange publisher — објекат мора да емитује сигнал пре промене @Published својства. Combine преноси сигнал у граф зависности SwiftUI-ја, који означава све зависне view-ове као оне који захтевају ажурирање. Ово се дешава синхроно пре промене вредности.
class WeatherService: ObservableObject {
@Published var temperature: Double = 22.0
@Published var city: String = "Moscow"
}
struct WeatherView: View {
@ObservedObject var weather: WeatherService
var body: some View {
VStack {
Text("\\(weather.city)")
Text("\\(weather.temperature)°C")
}
}
}
У листингу WeatherService је ObservableObject са два @Published својства. WeatherView декларише @ObservedObject var weather: WeatherService, добијајући инстанцу од родитеља. Када се temperature промени, objectWillChange се активира пре постављања нове вредности, SwiftUI поново исцртава WeatherView и приказује се тренутна температура. Претплатом аутоматски управља SwiftUI — програмер не мора да позива sink или dispose.
Први образац — прослеђивање модела кроз иницијализатор. Родитељ креира ObservableObject преко @StateObject-а и прослеђује га изведеним view-овима као @ObservedObject. Ово је стандардно хијерархијско прослеђивање података, при чему корени view управља животним циклусом модела, а све угнежђене компоненте се претплаћују на промене.
Други образац — EnvironmentObject, глобална верзија @ObservedObject-а кроз SwiftUI Environment. Објекат се убацује на нивоу сцене или кореног view-а и аутоматски је доступан свим изведеним компонентама без експлицитног прослеђивања кроз иницијализаторе. Унутар изведеног view-а, @EnvironmentObject ради слично @ObservedObject-у, али добија објекат из окружења.
Трећи образац — композиција више ObservableObject-а. У сложеним апликацијама view може да посматра више објеката: @ObservedObject var user: UserService, @ObservedObject var network: NetworkMonitor. Ово раздваја одговорност између сервиса и чува тестабилност сваке компоненте.
struct DashboardView: View {
@ObservedObject var user: UserViewModel
@ObservedObject var network: NetworkMonitor
var body: some View {
VStack {
Text("Добродошли, \\(user.name)")
HStack {
Circle()
.fill(network.isConnected ? Color.green : Color.red)
.frame(width: 10, height: 10)
}
}
}
}
DashboardView посматра UserViewModel и NetworkMonitor. Сваки објекат је одговоран за своју област података и независно обавештава view о променама. Ако се мрежа искључи, NetworkMonitor мења isConnected, и SwiftUI поново исцртава DashboardView, ажурирајући боју индикатора. Композиција ObservableObject-а је преферирани начин организовања података у SwiftUI апликацијама.
@Published је Property Wrapper из Combine-а који аутоматски додаје издавача својству унутар ObservableObject-а. Када се @Published својство промени, Combine генерише догађај кроз objectWillChange publisher. SwiftUI се претплаћује на овог publisher-а при коришћењу @ObservedObject или @StateObject и поново исцртава view при свакој новој вредности.
@Published подржава све типове, укључујући опционе, колекције и прилагођене структуре. Међутим, за колекције (низове, речнике) SwiftUI прати само замену референце, а не промену садржаја. Да бисте открили додавање или уклањање елемента, потребно је поново доделити целу колекцију или користити ObservableObject са ручним objectWillChange.send().
Важан детаљ: @Published мора да се налази само унутар класе која имплементира ObservableObject. Коришћење @Published ван ObservableObject-а ће изазвати грешку компајлирања. Такође, @Published се не може применити на својства лене иницијализације (lazy var) или израчуната својства (computed property).
Најкритичнија грешка — коришћење @ObservedObject за креирање објекта. Ако напишете @ObservedObject var model = UserViewModel() у родитељском view-у, при сваком рендеровању ће се креирати нова инстанца UserViewModel-а. Подаци ће бити изгубљени, а @Published претплате поново креиране. Увек користите @StateObject за креирање и @ObservedObject само за пријем готовог објекта.
Друга грешка — мењање @Published својстава ван главне нити. ObservableObject користи Combine, који захтева слање промена на главној нити (main actor). Ако промените @Published у позадинској нити, SwiftUI може поново да исцрта view у неодговарајућем тренутку, изазивајуći race conditions. Користите DispatchQueue.main.async или @MainActor за ажурирање.
Трећи проблем — циклична ажурирања. Ако промена @Published укључује нуспојаве које поново мењају @Published, настаје бесконачна петља поновног исцртавања. Решење: користите заштитне заставице (isUpdating) или раздвојите логику на различите ObservableObject-е са јасним границама одговорности.
Често постављана питања
Да, SwiftUI подржава @ObservedObject var model: UserViewModel?. Међутим, view неће бити претплаћен на промене док је објекат nil. При додели вредности, претплата се активира аутоматски.
@ObservedObject добија објекат кроз иницијализатор, @EnvironmentObject — кроз SwiftUI Environment. @EnvironmentObject не захтева експлицитно прослеђивање кроз конструкторе, али објекат мора бити убачен на горњем нивоу хијерархије.
Позовите objectWillChange.send() пре промене својства. Ово је корисно ако @Published није прикладан (на пример, за израчуната својства или операције са колекцијама где је потребно пријавити промену пре мутације).
@ObservedObject и @Published прате замену референце, а не мутацију садржаја колекције. За поновно исцртавање потребно је поново доделити низ: items.append(newItem) → items = items или користити objectWillChange.send() пре мутације.
Не, @ObservedObject је SwiftUI Property Wrapper доступан само унутар типова који имплементирају протокол View. За обичне структуре користите Combine директно са ObservableObjectPublisher.
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође