@Published: co to je, princip fungování a aplikace

Autor: IT Sectr Publikováno: 2026-06-19 Doba čtení: 8 min

@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

  • @Published — property wrapper pro automatické publikování změn vlastností ObservableObject ve SwiftUI a Combine
  • Mechanismus: při změně hodnoty je voláno objectWillChange, což spouští překreslení přihlášených view
  • Publisher je přístupný prostřednictvím projekce $property — lze se přihlásit, kombinovat a transformovat tok
  • ObservedObject a StateObject se automaticky přihlašují k @Published vlastnostem — ruční přihlášení není nutné
  • iOS 17+ makro @Observable nabízí alternativu, ale @Published zůstává standardem pro Combine pipeline

Co je @Published?

@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í.

Jak funguje @Published

@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:

swift
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).

@Publikováno a Combine

@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:

swift
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.

@Published vs makro @Observable

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í.

Běžné chyby s @Published

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.

Příklady kódu

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:

swift
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():

swift
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

Lze použít @Published ve struktuře?

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.

Jak @Published funguje s poli a slovy?

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ů.

Čím se @Published liší od @State?

@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.

Je @Published nutný pro každou vlastnost ObservableObject?

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í”.

Jak @Published funguje s Core Data?

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í

  • @Published — property wrapper z Combine, automaticky publikuje změny vlastností ObservableObject pro SwiftUI a Combine pipeline
  • Mechanismus: willSet pozorovatel volá objectWillChange.send(), generuje publisher prostřednictvím projekce $property
  • Combine: @Published poskytuje publisher pro debounce, map, combineLatest a další operátory — je mostem mezi UI a reaktivními pipeline
  • @Observable (iOS 17+) — alternativa pro nové projekty, ale @Published zůstává standardem pro Combine a zpětnou kompatibilitu
  • Chyby: @Published nefunguje ve strukturách, nesleduje mutaci referenčních typů, nadměrný @Published zvyšuje překreslení
  • Best practice: označujte @Published pouze vlastnosti ovlivňující UI, rozdělujte velké ObservableObject na několik malých
  • Assign: assign(to: &$property) ve Swift 5.9 umožňuje přímé přihlášení publisheru k vlastnosti @Published

Vyvineme 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í.

Prodiskutovat projekt

Přečtěte si také