@Published — är en property wrapper från Combine-ramverket som automatiskt publicerar ändringar av en klass egenskap som följer ObservableObject-protokollet. När värdet för en egenskap märkt med @Published ändras, tar SwiftUI emot en signal via objectWillChange och ritar om alla vyer som prenumererar på detta objekt. Enligt Apple Combine Framework Documentation (2025) genererar @Published en Publisher som kan transformeras ytterligare genom Combine-operatorerna: map, filter, debounce och andra. Detta gör @Published till en viktig brygga mellan data och användargränssnittet i MVVM-arkitekturen.
Huvudpunkter
objectWillChange, vilket utlöser omritning av prenumererade vyer$property — man kan prenumerera, kombinera och transformera flödet@Published — är en property wrapper definierad i Combine-modulen som ger en klass egenskap möjligheten att automatiskt meddela prenumeranter om ändringar. Den kan endast tillämpas inom en klass (inte i en struktur) och endast på egenskaper i en klass som följer ObservableObject-protokollet.
När värdet för en @Published-egenskap ändras genererar Combine en händelse genom den inbyggda publishern, tillgänglig via dollarprefix: $propertyName. Denna publisher är en ObservableObjectPublisher, som tillhör ObservableObject själv. SwiftUI prenumererar automatiskt på den när en vy använder @ObservedObject eller @StateObject, och ritar om vyn vid varje ändring av en @Published-egenskap inuti objektet.
Enligt Matt Neuburgs bok „IOS 18 Programming Fundamentals with Swift” (2025) är @Published en bekväm omslag runt willSet-mönstret som automatiskt anropar objectWillChange.send(). Kompilatorn vecklar faktiskt ut @Published till en beräknad egenskap med en willSet-observatör, vilket ger noll overhead vid körning jämfört med manuell implementering.
Använd @Published för alla ObservableObject-egenskaper vars ändringar ska reflekteras i gränssnittet. För egenskaper som inte påverkar UI minskar vanliga stored properties utan @Published antalet onödiga omritningar.
@Published genererar två nyckelelement vid kompilering. Det första — en lagrad egenskap med en willSet-observatör som anropar objectWillChange.send() innan det nya värdet skrivs. Det andra — projektionen $propertyName som returnerar en Published.Publisher som kan användas direkt i Combine-pipelines.
Betrakta klassen Settings med tre egenskaper: två @Published och en vanlig:
class Settings: ObservableObject {
@Published var username: String = "Guest"
@Published var isDarkMode = false
var lastLogin: Date = Date() // utan @Published
}
När username eller isDarkMode ändras ritar SwiftUI om alla vyer som prenumererar på Settings-instansen. Ändring av lastLogin utlöser ingen omritning. Om du behöver manuellt meddela prenumeranter om ändring av en vanlig egenskap kan du anropa objectWillChange.send() i willSet-observatören.
En viktig detalj: @Published publicerar ändringar endast vid direkt tilldelning till egenskapen. Om egenskapen är av referenstyp (klass) och dess interna tillstånd ändras utan att referensen ersätts, kommer @Published inte att upptäcka det. I sådana fall krävs manuell sändning av händelsen eller ersättning med en värdetyp (struktur).
@Published är nära integrerat med Combine — varje @Published-egenskap tillhandahåller automatiskt en publisher tillgänglig via projektionen $propertyName. Detta gör det möjligt att tillämpa Combine-operatorer för filtrering, transformering, kombination och fördröjd bearbetning av värden.
Ett typiskt scenario — sökning med debounce. Inmatningsfältet är bundet till den @Published-egenskapen searchText, men begäran till servern ska endast skickas efter en paus på 300 ms. Combine med $searchText.debounce löser detta på en rad:
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) { }
}
Enligt John Sundells artikel (Swift by Sundell, 2024) är kombinationen av @Published med Combine ett standardmönster för reaktiva pipeliner i SwiftUI-applikationer: validation, debounce, throttle, combineLatest, merge med andra publishers. @Published fungerar som en brygga mellan imperativ UI-kod och reaktiv Combine.
Med lanseringen av iOS 17 introducerade Apple @Observable-makrot, som erbjuder ett alternativt tillvägagångssätt för reaktivitet utan ObservableObject och @Published. @Observable spårar automatiskt åtkomst till egenskaper på läsnivå, inte skrivnivå, vilket ger mer exakta omritningar — endast den vy som läser den specifikt ändrade egenskapen uppdateras.
Men det betyder inte att @Published är föråldrad. @Published förblir nödvändig när integration med Combine-pipelines behövs — projektionen $propertyName ger en publisher som @Observable inte har. Dessutom, för bakåtkompatibilitet med iOS 16 och äldre, är @Published+ObservableObject det enda alternativet. Enligt Apple WWDC 2023-sessionen „Discover Observation in SwiftUI” rekommenderar Apple @Observable för nya projekt, men behåller uttryckligen stödet för @Published för befintlig kod och Combine-scenarier.
I praktiken använder många projekt en hybridansats: nya datamodeller skrivs med @Observable, medan befintliga ObservableObject med @Published förblir utan omfaktorering. @Published är också oersättlig när fin kontroll över publicering krävs — till exempel att fördröja meddelandet tills batchuppdateringen av flera egenskaper är klar.
Första misstaget — tillämpning av @Published i en struktur. Kompilatorn visar ett fel: „Property wrapper cannot be applied to a computed property” eller „'@Published' is only available on members of a class”. @Published kräver referenssemantik eftersom ObservableObjectPublisher är en klass som måste vara unik för varje instans.
Andra misstaget — mutering av innehållet i en referensegenskap utan att ersätta referensen. Om en @Published-egenskap är av typen array [String] och du anropar array.append("new"), kommer @Published inte att upptäcka ändringen eftersom referensen till arrayen inte har ändrats. Lösning: tilldela egenskapen ett nytt värde array = array + ["new"] eller använd objectWillChange.send() manuellt.
Tredje misstaget — för många @Published-egenskaper. Varje @Published-egenskap utlöser omritning av alla vyer som prenumererar på ObservableObject, inte bara de som läser denna egenskap. Enligt Point-Free (2025) minskar uppdelningen av en stor ObservableObject i flera små med @StateObject och @EnvironmentObject antalet onödiga omritningar och förbättrar prestandan.
Första exemplet — ViewModel för ett registreringsformulär med validering. @Published-egenskaperna email och password utlöser visning av valideringsfel genom Combine-pipelinen:
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)
}
}
Andra exemplet — manuell publicering för en samling referenselement. Istället för att ersätta hela arrayen vid varje ändring inuti ett element används 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() // manuellt meddelande
}
}
Tredje exemplet — Assign till en @Published-egenskap via Combine. Med den nya syntaxen i Swift 5.9 kan man direkt tilldela via projektionen assign(to: &$property) utan Optional-omslag. Detta är den kortaste vägen att koppla en publisher till en @Published-egenskap utan att skapa en prenumeration.
Vanliga frågor
Nej, @Published kan endast tillämpas inom en klass som följer ObservableObject. I strukturer använder du @State för lokalt tillstånd eller @Bindable med @Observable-makrot i iOS 17+. Ett försök att tillämpa @Published i en struktur kommer att orsaka ett kompileringsfel.
Korrekt: tilldela ett nytt värde i sin helhet (array = array + ["new"]). @Published spårar ersättning av referensen, inte mutering av innehållet. För samlingar av referenstyper, använd manuellt anrop av objectWillChange.send() efter mutering av elementens interna tillstånd.
@State är avsett för lokalt tillstånd inom en vy och fungerar endast med värdetyper. @Published — för ObservableObject-egenskaper som kan läsas av flera vyer via @ObservedObject eller @EnvironmentObject. @State är enklare, @Published är kraftfullare tack vare integrationen med Combine.
Endast för de vars ändringar ska uppdatera UI. Egenskaper för interna beräkningar, cache eller temporära flaggor kräver inte @Published — detta minskar antalet onödiga omritningar. Använd @Published som en signal –den här egenskapen är viktig för gränssnittet”.
SwiftUI integreras med Core Data genom @FetchRequest och @ObservedObject för NSManagedObject. ManagedObject följer redan ObservableObject, så @Published behövs inte — NSManagedObject själv meddelar om ändringar. @Published används i ViewModel-lagret mellan Core Data och UI för datatransformering.
Sammanfattning
objectWillChange.send(), genererar en publisher via projektionen $propertyassign(to: &$property) i Swift 5.9 möjliggör direkt prenumeration av en publisher på en @Published-egenskapVi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också