@Published — egy property wrapper a Combine keretrendszerből, amely automatikusan közzéteszi az ObservableObject protokollnak megfelelő osztály tulajdonságának változásait. Amikor a @Published-del jelölt tulajdonság értéke megváltozik, a SwiftUI jelet kap a objectWillChange-en keresztül, és újrarajzolja az összes, erre az objektumra feliratkozott nézetet. Az Apple Combine Framework Documentation (2025) szerint a @Published egy Publisher-t generál, amely tovább transzformálható a Combine operátorokkal: map, filter, debounce és mások. Ez teszi a @Published-et kulcsfontosságú hídá az adatok és a felhasználói felület között az MVVM architektúrában.
Főbb pontok
objectWillChange, ami kiváltja a feliratkozott nézetek újrarajzolását$property projekción keresztül — fel lehet iratkozni, kombinálni és transzformálni az adatfolyamot@Published — egy property wrapper, amely a Combine modulban van definiálva, és lehetővé teszi egy osztály tulajdonságának, hogy automatikusan értesítse a feliratkozókat a változásokról. Csak osztályon belül (nem struktúrában) és csak az ObservableObject protokollnak megfelelő osztály tulajdonságaira alkalmazható.
Amikor egy @Published tulajdonság értéke megváltozik, a Combine eseményt generál a beépített publisher-en keresztül, amely a dollár előtaggal érhető el: $propertyName. Ez a publisher egy ObservableObjectPublisher, amely magához az ObservableObject-hez tartozik. A SwiftUI automatikusan feliratkozik rá, amikor egy nézet @ObservedObject vagy @StateObject használ, és újrarajzolja a nézetet az objektumon belüli bármely @Published tulajdonság változásakor.
Matt Neuburg „IOS 18 Programming Fundamentals with Swift” (2025) című könyve szerint a @Published egy kényelmes burkoló a willSet pattern körül, amely automatikusan meghívja a objectWillChange.send()-et. A fordító gyakorlatilag egy számított tulajdonsággá bontja ki a @Published-et egy willSet megfigyelővel, ami nulla többletterhelést jelent futásidőben a kézi implementációhoz képest.
Használja a @Published-et minden olyan ObservableObject tulajdonsághoz, amelyek változásainak tükröződniük kell a felületen. Azokhoz a tulajdonságokhoz, amelyek nem befolyásolják a UI-t, a @Published nélküli szokásos stored properties csökkenti a szükségtelen újrarajzolások számát.
@Published két kulcselemet generál fordításkor. Az első — egy tárolt tulajdonság egy willSet megfigyelővel, amely meghívja a objectWillChange.send()-et az új érték írása előtt. A második — a $propertyName projekció, amely egy Published.Publisher-t ad vissza, ami közvetlenül használható a Combine pipeline-okban.
Tekintsük a Settings osztályt három tulajdonsággal: kettő @Published és egy szokásos:
class Settings: ObservableObject {
@Published var username: String = "Guest"
@Published var isDarkMode = false
var lastLogin: Date = Date() // @Published nélkül
}
A username vagy isDarkMode változásakor a SwiftUI újrarajzolja a Settings példányra feliratkozott összes nézetet. A lastLogin változása nem vált ki újrarajzolást. Ha kézzel szeretné értesíteni a feliratkozókat egy szokásos tulajdonság változásáról, meghívhatja a objectWillChange.send()-et a willSet megfigyelőben.
Fontos részlet: a @Published csak közvetlen értékadáskor teszi közzé a változásokat. Ha a tulajdonság referenciatípusú (osztály), és a belső állapota a referencia cseréje nélkül változik, a @Published nem érzékeli azt. Ilyen esetekben kézi eseményküldésre vagy értéktípusra (struktúrára) cserélésre van szükség.
@Published szorosan integrálódik a Combine-nal — minden @Published tulajdonság automatikusan biztosít egy publisher-t, amely a $propertyName projekción keresztül érhető el. Ez lehetővé teszi a Combine operátorok alkalmazását szűréshez, transzformációhoz, kombináláshoz és késleltetett értékfeldolgozáshoz.
Egy tipikus forgatókönyv — keresés debounce-szal. A beviteli mező a @Published searchText tulajdonsághoz van kötve, de a kérést a szerverhez csak 300 ms szünet után kell elküldeni. A Combine a $searchText.debounce-szal egy sorban megoldja ezt:
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) { }
}
John Sundell cikke (Swift by Sundell, 2024) szerint a @Published és a Combine kombinálása standard minta a reaktív pipeline-okhoz SwiftUI alkalmazásokban: validation, debounce, throttle, combineLatest, merge más publisher-ekkel. A @Published hídként működik az imperatív UI kód és a reaktív Combine között.
Az iOS 17 megjelenésével az Apple bevezette a @Observable makrót, amely alternatív megközelítést kínál a reaktivitáshoz ObservableObject és @Published nélkül. A @Observable automatikusan nyomon követi a tulajdonságokhoz való hozzáférést olvasási szinten, nem írási szinten, ami pontosabb újrarajzolást eredményez — csak az a nézet frissül, amelyik az adott megváltoztatott tulajdonságot olvassa.
Ez azonban nem jelenti azt, hogy a @Published elavult. A @Published továbbra is szükséges, amikor a Combine pipeline-okkal való integrációra van szükség — a $propertyName projekció olyan publisher-t biztosít, amilyennel a @Observable nem rendelkezik. Ezenkívül az iOS 16 és korábbi verziókkal való visszafelé kompatibilitás miatt a @Published+ObservableObject az egyetlen lehetőség. Az Apple WWDC 2023 „Discover Observation in SwiftUI” ülésszakasz szerint az Apple az @Observable-t ajánlja új projektekhez, de kifejezetten fenntartja a @Published támogatását a meglévő kódhoz és a Combine forgatókönyvekhez.
A gyakorlatban sok projekt hibrid megközelítést használ: az új adatmodelleket @Observable-val írják, a meglévő ObservableObject-ek @Published-del pedig refaktorálás nélkül maradnak. A @Published akkor is nélkülözhetetlen, amikor finom kontrollra van szükség a közzététel felett — például az értesítés késleltetése több tulajdonság batch frissítésének befejeződéséig.
Első hiba — a @Published alkalmazása struktúrában. A fordító hibát jelez: „Property wrapper cannot be applied to a computed property” vagy „'@Published' is only available on members of a class”. A @Published referenciális szemantikát igényel, mert az ObservableObjectPublisher egy osztály, amelynek minden példányhoz egyedinek kell lennie.
Második hiba — referencia tulajdonság tartalmának megváltoztatása a referencia cseréje nélkül. Ha egy @Published tulajdonság típusa [String] tömb, és ön meghívja a array.append("new")-t, a @Published nem érzékeli a változást, mert a tömbre mutató referencia nem változott. Megoldás: rendeljen új értéket a tulajdonsághoz array = array + ["new"] vagy használja kézzel a objectWillChange.send()-et.
Harmadik hiba — túl sok @Published tulajdonság. Minden @Published tulajdonság az ObservableObject-re feliratkozott összes nézet újrarajzolását kiváltja, nem csak azokét, amelyek ezt a tulajdonságot olvassák. A Point-Free (2025) szerint egy nagy ObservableObject több kicsire bontása @StateObject és @EnvironmentObject segítségével csökkenti a szükségtelen újrarajzolások számát és javítja a teljesítményt.
Első példa — regisztrációs űrlap ViewModel-je validációval. A @Published email és password tulajdonságok a Combine pipeline-on keresztül kiváltják a validációs hibák megjelenítését:
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)
}
}
Második példa — kézi közzététel referencia elemek gyűjteményéhez. Ahelyett, hogy az egész tömböt lecserélné minden elemen belüli változáskor, a objectWillChange.send() használata:
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() // kézi értesítés
}
}
Harmadik példa — Assign egy @Published tulajdonsághoz Combine-on keresztül. A Swift 5.9 új szintaxisát használva közvetlenül hozzárendelhető a assign(to: &$property) projekción keresztül Optional burkoló nélkül. Ez a legrövidebb út egy publisher és egy @Published tulajdonság összekapcsolására anélkül, hogy feliratkozást hoznánk létre.
Gyakran Ismételt Kérdések
Nem, a @Published csak ObservableObject-nek megfelelő osztályon belül alkalmazható. Struktúrákban használja a @State-t lokális állapothoz vagy a @Bindable-t az @Observable makróval iOS 17+-ban. A @Published struktúrában való alkalmazásának kísérlete fordítási hibát okoz.
Helyesen: rendeljen új értéket egészében (array = array + ["new"]). A @Published a referencia cseréjét követi, nem a tartalom megváltoztatását. Referenciatípusú gyűjtemények esetén használja a objectWillChange.send() kézi meghívását az elemek belső állapotának megváltoztatása után.
@State egy nézeten belüli lokális állapothoz való, és csak értéktípusokkal működik. A @Published — ObservableObject tulajdonságokhoz, amelyeket több nézet is olvashat @ObservedObject vagy @EnvironmentObject segítségével. A @State egyszerűbb, a @Published erősebb a Combine integrációnak köszönhetően.
Csak azokhoz, amelyek változásainak frissíteniük kell a UI-t. A belső számításokhoz, győrűtérhez vagy ideiglenes jelzőkhöz nem szükséges @Published — ez csökkenti a szükségtelen újrarajzolások számát. Használja a @Published-et jeleként: „ez a tulajdonság fontos a felület számára”.
A SwiftUI a Core Data-val a @FetchRequest és az NSManagedObject-hez való @ObservedObject segítségével integrálódik. A ManagedObject már megfelel az ObservableObject-nek, így a @Published nem szükséges — az NSManagedObject maga értesít a változásokról. A @Published a ViewModel rétegben használatos a Core Data és a UI között adat transzformációhoz.
Összefoglaló
objectWillChange.send()-et, és publisher-t generál a $property projekción keresztülassign(to: &$property) a Swift 5.9-ben lehetővé teszi a publisher közvetlen feliratkoztatását egy @Published tulajdonságraKulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is