@Published — је property wrapper из framework-а Combine који автоматски објављује промене својства класе која је у складу са протоколом ObservableObject. Када се вредност својства означеног са @Published промени, SwiftUI прима сигнал путем objectWillChange и поново исцртава све view-ове који су претплаћени на овај објекат. Према Apple Combine Framework Documentation (2025), @Published генерише Publisher који се може додатно трансформисати коришћећем оператора Combine: map, filter, debounce и других. То чини @Published кључном везом између података и корисничког интерфејса у архитектури MVVM.
Главно
objectWillChange, што покреће поновно исцртавање претплаћених view-ова$property — може се претплаћивати, комбиновати и трансформисати ток@Published — је property wrapper дефинисан у модулу Combine који додаје својству класе могућност автоматског обавештавања претплатника о променама. Може се примењивати само унутар класе (не у структури) и само на својства класе која је у складу са протоколом ObservableObject.
Када се вредност @Published својства промени, Combine генерише догађај путем уграђеног publisher-а, доступног путем префикса долара: $propertyName. Овај publisher је ObservableObjectPublisher, који припада самом ObservableObject-у. SwiftUI се автоматски претплаћује на њега када view користи @ObservedObject или @StateObject, и поново исцртава view при свакој промени било којег @Published својства унутар објекта.
Према њизи Мата Њубурга «IOS 18 Programming Fundamentals with Swift» (2025), @Published је практично омотање над pattern-ом willSet, који автоматски позива objectWillChange.send(). Компилер развија @Published у израчунато својство са willSet опсервером, што даје нулти оверхед у радном окружењу у поређењу са ручном имплементацијом.
Користите @Published за сва @Published својства ObservableObject чије промене треба да се одразе у интерфејсу. За својства која не утичу на UI, обичне stored properties без @Published смањују број непотребних поновних исцртавања.
@Published генерише два кључна елемента при компилацији. Први — складиштено својство са willSet опсервером који позива objectWillChange.send() пре записивања нове вредности. Други — пројекција $propertyName која враћа Published.Publisher који се може користити директно у Combine пајплајновима.
Размотримо класу Settings са три својства: два @Published и једно обично:
class Settings: ObservableObject {
@Published var username: String = "Guest"
@Published var isDarkMode = false
var lastLogin: Date = Date() // без @Published
}
При промени username или isDarkMode, SwiftUI поново исцртава све view-ове претплаћене на инстанцу Settings. Промена lastLogin неће покренути поновно исцртавање. Ако желите да ручно обавестите претплатнике о промени обичног својства, можете позвати objectWillChange.send() у willSet опсерверу.
Важан детаљ: @Published објављује промене само при директном уписивању у својство. Ако је својство референциог типа (класа) и његово унутрашње стање се промени без замене референце, @Published то неће приметити. У таквим случајевима потребно је ручно слање догађаја или замена типом вредности (структуром).
@Published је чврсто интегрисан са Combine-ом — свако @Published својство автоматски пружа publisher доступан путем пројекције $propertyName. То омогућава примену Combine оператора за филтрирање, трансформацију, комбиновање и каснену обраду вредности.
Типичан сценарио — претрага са debounce-ом. Поље за унос је повезано са @Published својством searchText, али захтев ка серверу треба да се шаље тек након паузе од 300 мс. Combine са $searchText.debounce решава то у једној линији:
class SearchViewModel: ObservableObject {
@Published var searchText = ""
@Published var results: [String] = []
private var cancellables = Set<AnyCancellable>()
init() {
setupSearchSubscription()
}
private func setupSearchSubscription() {
$searchText
.debounce(for: .milliseconds(300), scheduler: RunLoop.main)
.removeDuplicates()
.sink { [weak self] text in
self?.performSearch(text)
}
.store(in: &cancellables)
}
private func performSearch(_ text: String) { }
}
Према чланку Џона Сандела (Swift by Sundell, 2024), комбиновање @Published са Combine-ом је стандардни pattern за реактивне пајплајнове у SwiftUI апликацијама: validation, debounce, throttle, combineLatest, merge са другим publishers. @Published делује као веза између императивног UI кода и реактивног Combine-а.
Са изласком iOS 17, Apple је представила макро @Observable, који нуди алтернативни приступ реактивности без ObservableObject и @Published. @Observable автоматски прати приступ својствима на нивоу читања, не записивања, што даје прецизније поновно исцртавање — ажурира се само онај view који чита конкретно измењено својство.
Међутим, то не значи да је @Published застарео. @Published остаје потребан када је потребна интеграција са Combine пајплајновима — пројекција $propertyName даје publisher-а који @Observable нема. Поред тога, за уназад компатибилност са iOS 16 и старијим верзијама, @Published+ObservableObject је једина опција. Према Apple WWDC 2023 сесији «Discover Observation in SwiftUI», Apple препоручује @Observable за нове пројекте, али експлицитно задржава подршку за @Published за постоћећи код и Combine сценарије.
У пракси, многи пројекти користе хибридни приступ: нови модели података пишу се са @Observable, а постоћећи ObservableObject са @Published остају без рефакторисања. @Published је такође незамењив када је потребна прецизна контрола над објављивањем — на пример, одлагање обавештавања до завршетка групног ажурирања више својстава.
Прва грешка — примена @Published у структури. Компилер ће приказати грешку: «Property wrapper cannot be applied to a computed property» или «'@Published' is only available on members of a class». @Published захтева референцну семантику, јер је ObservableObjectPublisher класа која мора бити јединствена за сваку инстанцу.
Друга грешка — мутација садржаја референцног својства без замене референце. Ако @Published својство има тип низа [String] и позовете array.append("new"), @Published неће приметити промену јер се референца на низ није промењена. Решење: додијелите својству нову вредност array = array + ["new"] или користите objectWillChange.send() ручно.
Трећа грешка — прекомернан број @Published својстава. Свако @Published својство покреће поновно исцртавање свих view-ова претплаћених на ObservableObject, не само оних који читају то својство. Према Point-Free (2025), подела једног великог ObservableObject-а на неколико малих са @StateObject и @EnvironmentObject смањује број непотребних поновних исцртавања и побољшава перформансе.
Први пример — ViewModel формулара за регистрацију са валидацијом. @Published својства email и password покрећу приказ грешака валидације кроз Combine pipeline:
class RegistrationViewModel: ObservableObject {
@Published var email = ""
@Published var password = ""
@Published var emailError: String?
@Published var isFormValid = false
private var cancellables = Set<AnyCancellable>()
init() {
$email
.map { $0.contains("@") ? nil : "Invalid email" }
.assign(to: &$emailError)
.store(in: &cancellables)
$email.combineLatest($password)
.map { !$0.isEmpty && !$1.isEmpty }
.assign(to: &$isFormValid)
.store(in: &cancellables)
}
}
Други пример — ручно објављивање за колекцију референцних елемената. Уместо замене целог низа при свакој промени унутар елемента, користи се objectWillChange.send():
class TodoItem {
var title: String
var isDone = false
init(title: String) { self.title = title }
}
class TodoListViewModel: ObservableObject {
@Published var items: [TodoItem] = []
func toggle(item: TodoItem) {
item.isDone.toggle()
self.objectWillChange.send() // ручно обавештавање
}
}
Трећи пример — Assign на @Published својство путем Combine-а. Користећи нову синтаксу Swift 5.9, може се директно додијелити путем пројекције assign(to: &$property) без Optional омотача. То је најкраћи пут за повезивање publisher-а са @Published својством без креирања претплате.
Често постављана питања
Не, @Published се може примењивати само унутар класе која је у складу са ObservableObject. У структурама користите @State за локално стање или @Bindable са @Observable макром у iOS 17+. Покушај примене @Published у структури изазваће грешку компилације.
Исправно: додијељивајте нову вредност у целини (array = array + ["new"]). @Published прати замену референце, не мутацију садржаја. За колекције референцних типова користите ручни позив objectWillChange.send() након мутације унутрашњег стања елемената.
@State је намењен за локално стање унутар једног view-а и ради само са типовима вредности. @Published — за ObservableObject својства која могу читати више view-ова путем @ObservedObject или @EnvironmentObject. @State је једноставнији, @Published је моћнији захваљујући интеграцији са Combine-ом.
Само за она чије промене треба да ажурирају UI. Својства за унутрашње израчуне, кеш или привремене заставице не захтевају @Published — то смањује број непотребних поновних исцртавања. Користите @Published као сигнал «ово својство је важно за интерфејс».
SwiftUI се интегрише са Core Data путем @FetchRequest и @ObservedObject за NSManagedObject. ManagedObject је већ у складу са ObservableObject, па @Published није потребан — NSManagedObject сам обавештава о променама. @Published се користи у ViewModel слоју између Core Data и UI за трансформацију података.
Закључак
objectWillChange.send(), генеришући publisher кроз пројекцију $propertyassign(to: &$property) у Swift 5.9 омогућава директно претплаћивање publisher-а на @Published својствоРазвићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође