@Published — este un property wrapper din framework-ul Combine care publică automat modificările unei proprietăți a clasei conforme cu protocolul ObservableObject. Când valoarea proprietăți marcate cu @Published se schimbă, SwiftUI primește un semnal prin objectWillChange și redesenează toate view-urile abonate la acest obiect. Conform Apple Combine Framework Documentation (2025), @Published generează un Publisher care poate fi transformat suplimentar prin operatorii Combine: map, filter, debounce și alții. Acest lucru face din @Published o punte cheie între date și interfața utilizatorului în arhitectura MVVM.
Puncte principale
objectWillChange, ceea ce declanșează redesenarea view-urilor abonate$property — se poate abona, combina și transforma fluxul@Published — este un property wrapper definit în modulul Combine care adaugă unei proprietăți a clasei capacitatea de a notifica automat abonații despre modificări. Poate fi aplicat doar în interiorul unei clase (nu într-o structură) și numai proprietăților unei clase conforme cu protocolul ObservableObject.
Când valoarea unei proprietăți @Published se schimbă, Combine generează un eveniment prin publisher-ul încorporat, accesibil prin prefixul dolar: $propertyName. Acest publisher este ObservableObjectPublisher, care aparține însuși ObservableObject. SwiftUI se abonează automat la acesta când view-ul folosește @ObservedObject sau @StateObject și redesenează view-ul la orice schimbare a oricărei proprietăți @Published din interiorul obiectului.
Conform cărții lui Matt Neuburg „IOS 18 Programming Fundamentals with Swift” (2025), @Published este un wrapper convenabil peste pattern-ul willSet, care apelează automat objectWillChange.send(). Efectiv, compilatorul desface @Published într-o proprietate calculată cu un observator willSet, ceea ce oferă un overhead zero la runtime în comparație cu implementarea manuală.
Folosiți @Published pentru toate proprietățile ObservableObject ale căror modificări trebuie să se reflecte în interfață. Pentru proprietățile care nu afectează UI, stored properties obișnuite fără @Published reduc numărul de redeseneări inutile.
@Published generează două elemente cheie la compilare. Primul — o proprietate stocată cu un observator willSet care apelează objectWillChange.send() înainte de scrierea noii valori. Al doilea — proiecția $propertyName care returnează un Published.Publisher ce poate fi folosit direct în pipeline-urile Combine.
Să considerăm clasa Settings cu trei proprietăți: două @Published și una obișnuită:
class Settings: ObservableObject {
@Published var username: String = "Guest"
@Published var isDarkMode = false
var lastLogin: Date = Date() // fără @Published
}
La modificarea username sau isDarkMode, SwiftUI redesenează toate view-urile abonate la instanța Settings. Modificarea lastLogin nu va declanșa redesenarea. Dacă trebuie să notificați manual abonații despre schimbarea unei proprietăți obișnuite, puteți apela objectWillChange.send() în observatorul willSet.
Un detaliu important: @Published publică modificările doar la scrierea directă în proprietate. Dacă proprietatea este de tip referință (clasă) și starea sa internă se schimbă fără înlocuirea referinței, @Published nu va detecta acest lucru. în astfel de cazuri este necesară trimiterea manuală a evenimentului sau înlocuirea cu un tip valoare (structură).
@Published este strâns integrat cu Combine — fiecare proprietate @Published oferă automat un publisher accesibil prin proiecția $propertyName. Acest lucru permite aplicarea operatorilor Combine pentru filtrare, transformare, combinare și procesare întârziată a valorilor.
Un scenariu tipic — căutarea cu debounce. Câmpul de intrare este legat de proprietatea @Published searchText, dar cererea la server trebuie trimisă doar după o pauză de 300 ms. Combine cu $searchText.debounce rezolvă aceasta într-o singură linie:
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) { }
}
Conform articolului lui John Sundell (Swift by Sundell, 2024), combinarea @Published cu Combine este un pattern standard pentru pipeline-uri reactive în aplicațiile SwiftUI: validation, debounce, throttle, combineLatest, merge cu alți publishers. @Published acționează ca o punte între codul UI imperativ și Combine reactiv.
Odată cu lansarea iOS 17, Apple a introdus macro-ul @Observable, care oferă o abordare alternativă la reactivitate fără ObservableObject și @Published. @Observable urmărește automat accesul la proprietăți la nivel de citire, nu de scriere, ceea ce oferă redeseneări mai precise — se actualizează doar view-ul care citește proprietatea specifică modificată.
Dar aceasta nu înseamnă că @Published este învechit. @Published rămâne necesar când este nevoie de integrare cu pipeline-urile Combine — proiecția $propertyName oferă un publisher pe care @Observable nu îl are. În plus, pentru compatibilitatea cu iOS 16 și versiunile anterioare, @Published+ObservableObject este singura opțiune. Conform sesiunii Apple WWDC 2023 „Discover Observation in SwiftUI”, Apple recomandă @Observable pentru proiecte noi, dar menține în mod explicit suportul pentru @Published pentru codul existent și scenariile Combine.
În practică, multe proiecte folosesc o abordare hibridă: modelele de date noi sunt scrise cu @Observable, iar ObservableObject-urile existente cu @Published rămân fără refactorizare. @Published este, de asemenea, de neînlocuit când este necesar un control fin asupra publicării — de exemplu, amânarea notificării până la finalizarea actualizării batch a mai multor proprietăți.
Prima greșeală — aplicarea @Published într-o structură. Compilatorul va afișa eroarea: „Property wrapper cannot be applied to a computed property” sau „'@Published' is only available on members of a class”. @Published necesită semantică de referință, deoarece ObservableObjectPublisher este o clasă care trebuie să fie unică pentru fiecare instanță.
A doua greșeală — mutarea conținutului unei proprietăți de tip referință fără înlocuirea referinței. Dacă o proprietate @Published este de tip matrice [String] și apelați array.append("new"), @Published nu va detecta schimbarea, deoarece referința la matrice nu s-a modificat. Soluția: atribuiți proprietății o nouă valoare array = array + ["new"] sau folosiți objectWillChange.send() manual.
A treia greșeală — numărul excesiv de proprietăți @Published. Fiecare proprietate @Published declanșează redesenarea tuturor view-urilor abonate la ObservableObject, nu doar a celor care citesc această proprietate. Conform Point-Free (2025), împărțirea unui ObservableObject mare în mai multe mai mici cu @StateObject și @EnvironmentObject reduce numărul de redeseneări inutile și îmbunătățește performanța.
Primul exemplu — ViewModel al unui formular de înregistrare cu validare. Proprietățile @Published email și password declanșează afișarea erorilor de validare prin pipeline-ul Combine:
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)
}
}
Al doilea exemplu — publicare manuală pentru o colecție de elemente de tip referință. În loc să înlocuiți întregul tablou la fiecare modificare într-un element, se folosește 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() // notificare manuală
}
}
Al treilea exemplu — Assign la o proprietate @Published prin Combine. Folosind noua sintaxă Swift 5.9, se poate atribui direct prin proiecția assign(to: &$property) fără încapsularea Optional. Aceasta este cea mai scurtă cale de a lega un publisher de o proprietate @Published fără a crea o abonare.
Întrebări frecvente
Nu, @Published poate fi aplicat doar în interiorul unei clase conforme cu ObservableObject. în structuri folosiți @State pentru starea locală sau @Bindable cu macro-ul @Observable în iOS 17+. încercarea de a aplica @Published într-o structură va provoca o eroare de compilare.
Corect: atribuiți o nouă valoare în întregime (array = array + ["new"]). @Published urmărește înlocuirea referinței, nu mutarea conținutului. Pentru colecții de tipuri referință, folosiți apelul manual objectWillChange.send() după mutarea stării interne a elementelor.
@State este destinat stării locale în cadrul unui singur view și funcționează doar cu tipuri valoare. @Published — pentru proprietățile ObservableObject care pot fi citite de mai multe view-uri prin @ObservedObject sau @EnvironmentObject. @State este mai simplu, @Published este mai puternic datorită integrării cu Combine.
Doar pentru acelea ale căror modificări trebuie să actualizeze UI. Proprietățile pentru calcule interne, cache sau flag-uri temporare nu necesită @Published — aceasta reduce numărul de redeseneări inutile. Folosiți @Published ca semnal „această proprietate este importantă pentru interfață”.
SwiftUI se integrează cu Core Data prin @FetchRequest și @ObservedObject pentru NSManagedObject. ManagedObject este deja conform cu ObservableObject, deci @Published nu este necesar — NSManagedObject înșuși notifică despre modificări. @Published este folosit în stratul ViewModel dintre Core Data și UI pentru transformarea datelor.
Concluzii
objectWillChange.send(), generând un publisher prin proiecția $propertyassign(to: &$property) în Swift 5.9 permite abonarea unui publisher direct la o proprietate @PublishedVom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și