@Published — je property wrapper z frameworku Combine, který automaticky publikuje změny vlastnosti třídy vyhovující protokolu ObservableObject. Když se hodnota vlastnosti označené @Published změní, SwiftUI obdrží signál prostřednictvím objectWillChange a překreslí všechny view přihlášené k tomuto objektu. Podle Apple Combine Framework Documentation (2025) generuje @Published Publisher, který lze dále transformovat pomocí operátorů Combine: map, filter, debounce a dalších. To činí @Published klíčovým mostem mezi daty a uživatelským rozhraním v architektuře MVVM.
Hlavní body
objectWillChange, což spouští překreslení přihlášených view$property — lze se přihlásit, kombinovat a transformovat tok@Published — je property wrapper definovaný v modulu Combine, který přidává vlastnosti třídy schopnost automaticky informovat odběratele o změnách. Lze jej aplikovat pouze uvnitř třídy (ne ve struktuře) a pouze na vlastnosti třídy vyhovující protokolu ObservableObject.
Když se hodnota vlastnosti @Published změní, Combine vygeneruje událost prostřednictvím vestavěného publisheru, přístupného pomocí prefixu dolaru: $propertyName. Tento publisher je ObservableObjectPublisher, který patří samotnému ObservableObject. SwiftUI se k němu automaticky přihlásí, když view používá @ObservedObject nebo @StateObject, a překreslí view při každé změně kterékoli vlastnosti @Published uvnitř objektu.
Podle knihy Matta Neuburga „IOS 18 Programming Fundamentals with Swift” (2025) je @Published pohodlný obal kolem vzoru willSet, který automaticky volá objectWillChange.send(). Kompilátor fakticky rozbaluje @Published na vypočítanou vlastnost s willSet pozorovatelem, což poskytuje nulovou režii za běhu ve srovnání s ruční implementací.
Používejte @Published pro všechny vlastnosti ObservableObject, jejichž změny se mají odrážet v rozhraní. Pro vlastnosti, které neovlivňují UI, běžné stored properties bez @Published snižují počet zbytečných překreslení.
@Published generuje dva klíčové prvky při kompilaci. První — uložená vlastnost s willSet pozorovatelem, který volá objectWillChange.send() před zápisem nové hodnoty. Druhý — projekce $propertyName, která vrací Published.Publisher, jenž lze použít přímo v Combine pipeline.
Uvažujme třídu Settings se třemi vlastnostmi: dvěma @Published a jednou běžnou:
class Settings: ObservableObject {
@Published var username: String = "Guest"
@Published var isDarkMode = false
var lastLogin: Date = Date() // bez @Published
}
Při změně username nebo isDarkMode SwiftUI překreslí všechny view přihlášené k instanci Settings. Změna lastLogin nezpůsobí překreslení. Pokud potřebujete ručně informovat odběratele o změně běžné vlastnosti, můžete zavolat objectWillChange.send() v pozorovateli willSet.
Důležitý detail: @Published publikuje změny pouze při přímém zápisu do vlastnosti. Pokud je vlastnost referenčního typu (třída) a její vnitřní stav se změní bez nahrazení reference, @Published to nezjistí. V takových případech je nutné ruční odeslání události nebo nahrazení typem hodnoty (struktura).
@Published je úzce integrován s Combine — každá vlastnost @Published automaticky poskytuje publisher přístupný prostřednictvím projekce $propertyName. To umožňuje aplikovat operátory Combine pro filtrování, transformaci, kombinování a zpožděné zpracování hodnot.
Typický scénář — vyhledávání s debounce. Vstupní pole je svázáno s vlastností @Published searchText, ale požadavek na server by měl být odeslán až po pauze 300 ms. Combine s $searchText.debounce to řeší na jednom řádku:
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) { }
}
Podle článku Johna Sundella (Swift by Sundell, 2024) je kombinování @Published s Combine standardním vzorem pro reaktivní pipeline v aplikacích SwiftUI: validation, debounce, throttle, combineLatest, merge s jinými publishery. @Published funguje jako most mezi imperativním UI kódem a reaktivním Combine.
S vydáním iOS 17 Apple představila makro @Observable, které nabízí alternativní přístup k reaktivitě bez ObservableObject a @Published. @Observable automaticky sleduje přístup k vlastnostem na úrovni čtení, nikoli zápisu, což poskytuje přesnější překreslení — aktualizuje se pouze to view, které čte konkrétní změněnou vlastnost.
To však neznamená, že @Published je zastaralý. @Published zůstává nezbytný, když je potřeba integrace s Combine pipeline — projekce $propertyName poskytuje publisher, který @Observable nemá. Kromě toho je pro zpětnou kompatibilitu s iOS 16 a nižšími @Published+ObservableObject jedinou možností. Podle Apple WWDC 2023 relace „Discover Observation in SwiftUI” Apple doporučuje @Observable pro nové projekty, ale výslovně zachovává podporu pro @Published pro stávající kód a scénáře Combine.
V praxi mnoho projektů používá hybridní přístup: nové datové modely se píší s @Observable, zatímco stávající ObservableObject s @Published zůstávají bez refaktorování. @Published je také nepostradatelný, když je vyžadována jemná kontrola nad publikováním — například odložení oznámení do dokončení dávkové aktualizace více vlastností.
První chyba — aplikace @Published ve struktuře. Kompilátor zobrazí chybu: „Property wrapper cannot be applied to a computed property” nebo „'@Published' is only available on members of a class”. @Published vyžaduje referenční sémantiku, protože ObservableObjectPublisher je třída, která musí být pro každou instanci jedinečná.
Druhá chyba — mutace obsahu referenční vlastnosti bez nahrazení reference. Pokud má vlastnost @Published typ pole [String] a zavoláte array.append("new"), @Published změnu nezjistí, protože reference na pole se nezměnila. Řešení: přiřaďte vlastnosti novou hodnotu array = array + ["new"] nebo použijte objectWillChange.send() ručně.
Třetí chyba — nadměrný počet vlastností @Published. Každá vlastnost @Published spouští překreslení všech view přihlášených k ObservableObject, nejen těch, které tuto vlastnost čtou. Podle Point-Free (2025) rozdělení jednoho velkého ObservableObject na několik malých s @StateObject a @EnvironmentObject snižuje počet zbytečných překreslení a zlepšuje výkon.
První příklad — ViewModel registračního formuláře s validací. Vlastnosti @Published email a password spouštějí zobrazení validačních chyb prostřednictvím 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)
}
}
Druhý příklad — ruční publikování pro kolekci referenčních prvků. Místo nahrazení celého pole při každé změně uvnitř prvku se používá 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() // ruční oznámení
}
}
Třetí příklad — Assign na vlastnost @Published prostřednictvím Combine. S novou syntaxí Swift 5.9 lze přímo přiřadit pomocí projekce assign(to: &$property) bez obalu Optional. To je nejkratší cesta, jak propojit publisher s vlastností @Published bez vytváření odběru.
Často kladené otázky
Ne, @Published lze aplikovat pouze uvnitř třídy vyhovující ObservableObject. Ve strukturách používejte @State pro lokální stav nebo @Bindable s makrem @Observable v iOS 17+. Pokus o aplikaci @Published ve struktuře způsobí chybu kompilace.
Správně: přiřaďte novou hodnotu jako celek (array = array + ["new"]). @Published sleduje nahrazení reference, nikoli mutaci obsahu. Pro kolekce referenčních typů použijte ruční volání objectWillChange.send() po mutaci vnitřního stavu prvků.
@State je určen pro lokální stav v rámci jednoho view a funguje pouze s typy hodnot. @Published — pro vlastnosti ObservableObject, které mohou být čteny více view pomocí @ObservedObject nebo @EnvironmentObject. @State je jednodušší, @Published je výkonnější díky integraci s Combine.
Pouze pro ty, jejichž změny mají aktualizovat UI. Vlastnosti pro vnitřní výpočty, mezipaměť nebo dočasné příznaky nevyžadují @Published — to snižuje počet zbytečných překreslení. Používejte @Published jako signál „tato vlastnost je důležitá pro rozhraní”.
SwiftUI se integruje s Core Data prostřednictvím @FetchRequest a @ObservedObject pro NSManagedObject. ManagedObject již vyhovuje ObservableObject, takže @Published není nutný — NSManagedObject sám informuje o změnách. @Published se používá ve vrstvě ViewModel mezi Core Data a UI pro transformaci dat.
Shrnutí
objectWillChange.send(), generuje publisher prostřednictvím projekce $propertyassign(to: &$property) ve Swift 5.9 umožňuje přímé přihlášení publisheru k vlastnosti @PublishedVyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také