@StateObject: vad det är, skapa och hantera ObservableObject

Författare: IT Sectr Publicerad: 2026-06-26 Lästid: 9 min

@StateObject är en property wrapper i SwiftUI som skapar och äger en ObservableObject-instans under hela Viewns livscykel. När View först visas på skärmen initierar @StateObject objektet och lagrar det tills View tas bort från minnet. Detta garanterar att data inte återställs vid ombyggnad av gränssnittet — till exempel vid temabytest eller uppdatering av förälder-View. Enligt Apple Developer Documentation (2025) bör @StateObject användas som den främsta sanningskällan (source of truth) för ObservableObject i SwiftUI-hierarkin, medan underordnade View får det redan skapade objektet via @ObservedObject eller @EnvironmentObject.

Huvudpunkter

  • @StateObject — property wrapper för att skapa och äga ObservableObject inuti View.
  • Engångsskapande — objektet initieras en gång under Viewns livstid och återskapas inte vid ombyggnationer.
  • Source of truth — @StateObject är sanningskällan i hierarkin, till skillnad från @ObservedObject.
  • Livscykel — objektet lever så länge View finns i minnet och förstörs tillsammans med det.
  • Initiering — @StateObject kräver ett initialvärde vid skapande, vanligtvis via init med parametrar.

Vad är @StateObject i SwiftUI

@StateObject är en property wrapper som introducerades i iOS 14 och som gör det möjligt för ett View att skapa och äga en instans av en klass som följer ObservableObject-protokollet. Till skillnad från @State som arbetar med värdetyper (strukturer), är @StateObject avsett för referenstyper — klasser som kan meddela SwiftUI om ändringar i sina egenskaper.

När ett View använder @StateObject var viewModel: MyViewModel, skapar SwiftUI automatiskt en MyViewModel-instans vid första visningen av View och lagrar den i frameworkets särskilda lagring. Vid varje uppdatering av View (till exempel vid ändring av förälderns tillstånd) återskapar SwiftUI inte objektet — det använder den befintliga instansen tills View tas bort från hierarkin.

Enligt Apple WWDC Session 10137 (2024) löser @StateObject problemet med dataförlust vid ombyggnad av View som fanns i iOS 13, när utvecklare var tvungna att skapa ObservableObject i förälder-View och skicka det via initieraren. Detta ledde till kodduplicering och risk för oavsiktlig återskapning av objektet.

swift
import SwiftUI

class CounterViewModel: ObservableObject {
    @Published var count: Int = 0
    
    func increment() {
        count += 1
    }
}

struct CounterView: View {
    @StateObject var viewModel = CounterViewModel()
    
    var body: some View {
        VStack {
            Text("Antal: \(viewModel.count)")
            Button("Öka", action: viewModel.increment)
        }
    }
}

Hur @StateObject fungerar

Mekanismen för @StateObject är baserad på integrationen av SwiftUI med Combine-frameworket. När ObservableObject markerar sina egenskaper med attributet @Published, prenumererar SwiftUI automatiskt på ändringar via den inbyggda publishern i ObservableObject-protokollet. När en publicerad egenskap ändras skickar objektet en signal via objectWillChange-publishern, vilket utlöser omritning av alla View som observerar detta objekt.

SwiftUI lagrar ObservableObject-instansen i en särskild lagring som är bunden till en specifik View-instans. Denna lagring skapas en gång vid första rendereringen och finns kvar tills View förstörs. Det är därför @StateObject garanterar stabiliteten för referensen till objektet — SwiftUI hanterar minnet automatiskt, utan att förlita sig på Viewns initierare.

Enligt objc.io — Thinking in SwiftUI (2025) använder den interna implementeringen av @StateObject en mekanism som liknar @State, men för referenstyper: SwiftUI skapar ett boxing-omslag runt objektet och hanterar dess livscykel via en egen allokerare, optimerad för frekventa ombyggnationer av View-hierarkin.

@StateObjects livscykel

  • Skapande — när View först visas på skärmen anropar SwiftUI objektets initierare och sparar referensen.
  • Ombyggnad — vid uppdatering av förälder-View återskapas inte objektet, den befintliga instansen används.
  • Förstörelse — när View lämnar skärmen och tas bort från hierarkin anropar SwiftUI objektets deinit.

@StateObject vs @ObservedObject: viktiga skillnader

Huvudskillnaden mellan @StateObject och @ObservedObject är vem som äger objektet. @StateObject skapar och lagrar objektet — det är ägaren. @ObservedObject observerar bara ett objekt som har skapats någon annanstans och skickats via initieraren eller en egenskap.

Egenskap@StateObject@ObservedObject
ÄgandeSkapar och äger objektetObserverar bara
InitieringInuti View via init/defaultUtifrån, skickas via parameter
LivscykelBunden till Viewns livscykelKontrolleras inte av View
ÅterskapandeÅterskapas inte vid uppdateringKan ersättas utifrån
iOS-versioniOS 14+iOS 13+

Regeln är enkel: om View skapar ObservableObject — använd @StateObject. Om View bara tar emot ett redan färdigt objekt från föräldern — använd @ObservedObject. Brott mot denna regel leder antingen till dataförlust (om du använder @ObservedObject för ägande) eller till överdriven objektsskapande (om du använder @StateObject för observation).

När ska man använda @StateObject

@StateObject bör användas i de View som är sanningskällan för en specifik datamängd. Typiska scenarier inkluderar skärmar med egen view model, rot-skärmar i navigationsstackar och modala presentationer som hanterar eget tillstånd.

  • Skärm med view model — varje skärm som hanterar egna data och logik bör skapa sin view model via @StateObject.
  • Rot-View — i en NavigationStack- eller TabView-hierarki skapar rotelementet data och underordnade får dem via @ObservedObject.
  • Modala fönster — .sheet och .fullScreenCover kräver ofta en egen @StateObject för att hantera ett formulär eller en process.
  • Lista med redigering — varje rad i en lista som innehåller ett redigeringsformulär bör ha sin egen @StateObject.
swift
struct ProfileView: View {
    @StateObject var viewModel = ProfileViewModel()
    
    var body: some View {
        NavigationStack {
            Form {
                TextField("Name", text: $viewModel.name)
                TextField("Email", text: $viewModel.email)
                Button("Spara") {
                    viewModel.saveProfile()
                }
            }
            .navigationTitle("Profile")
        }
    }
}

Initiering av @StateObject med parametrar

Initiering av @StateObject med parametrar kräver speciell syntax eftersom SwiftUI hanterar skapandet av objektet oberoende. Man kan inte bara skicka parametrar till initieraren — man måste använda en escaping closure eller en separat skapandemetod.

Enligt Swift by Sundell (2024) är den renaste metoden att använda en fabriksmetod eller en closure som SwiftUI anropar vid första skapandet av objektet. Ett alternativt tillvägagångssätt — initiera ObservableObject i förälder-View och skicka det via @StateObject med standardinitieraren.

swift
class UserViewModel: ObservableObject {
    @Published var user: User
    
    init(user: User) {
        self.user = user
    }
}

struct UserDetailView: View {
    @StateObject var viewModel: UserViewModel
    
    init(user: User) {
        _viewModel = StateObject(wrappedValue: UserViewModel(user: user))
    }
    
    var body: some View {
        Text(viewModel.user.name)
    }
}

Det är viktigt att komma ihåg att View-initieraren med @StateObject måste använda understreck före egenskapsnamnet (_viewModel) för att komma åt själva property wrappern, inte dess värde. Detta är ett standard Swift-mönster för att arbeta med property wrappers i initierare.

Vanliga misstag med @StateObject

Det vanligaste misstaget är att använda @ObservedObject istället för @StateObject för ett View som borde äga objektet. I detta fall kommer objektet att återskapas vid varje ombyggnad av föräldern, vilket leder till förlust av all ackumulerad data. Detta misstag är särskilt lömskt i komplexa hierarkier med NavigationStack eller TabView.

  • Dataförlust vid navigering — om en underordnad skärm använder @ObservedObject för sin egen view model, kommer data att återställas vid återgång och återöppning.
  • Minnesläcka — att skapa @StateObject i en förälder-View som aldrig tas bort kan leda till ackumulering av objekt om varje underordnad skärm också skapar @StateObject utan kontroll.
  • Objektsduplicering — att skicka ett ObservableObject till flera @StateObject i olika View skapar flera oberoende instanser som inte synkroniserar med varandra.

För att undvika dessa problem, följ den enkla regeln: en @StateObject per sanningskälla. Om data måste delas mellan flera skärmar — skapa @StateObject en gång i rot-View och skicka det via @ObservedObject eller @EnvironmentObject till underordnade element.

swift
// ❌ Fel: @ObservedObject för att äga ett objekt
struct BadView: View {
    @ObservedObject var vm = ViewModel() // kommer att återskapas vid varje uppdatering!
}

// ✅ Rätt: @StateObject för att äga
struct GoodView: View {
    @StateObject var vm = ViewModel() // skapades en gång för Viewns livstid
}

Vanliga frågor

Vad är skillnaden mellan @StateObject och @State?

@State arbetar med värdetyper (strukturer, strängar, tal) och lagrar värdet direkt i SwiftUI-lagringen. @StateObject arbetar med referenstyper — klasser som följer ObservableObject. @State är lämpligt för enkla lokala tillstånd, @StateObject för komplexa objekt med logik och publicerade egenskaper.

Kan man använda @StateObject i iOS 13?

Nej, @StateObject är endast tillgängligt från iOS 14 och uppåt. För iOS 13 använder du @ObservedObject och skapar ObservableObject i förälder-View via @State med manuell livscykelhantering. Ett alternativ är att använda @State med struct istället för class för data som inte kräver referenssemantik.

Vad händer om jag använder @StateObject i ett underordnat View där objektet skickas från föräldern?

Det underordnade View kommer att skapa sin egen kopia av ObservableObject, helt oberoende av föräldern. Ändringar i den ena kommer inte att återspeglas i den andra. Detta är nästan alltid ett misstag: använd @ObservedObject för att ta emot objektet från föräldern och @StateObject endast för att skapa ett nytt objekt inuti View.

När förstörs ett objekt som skapats via @StateObject?

Objektet förstörs när View som skapade det helt tas bort från SwiftUI-hierarkin. För en skärm i NavigationStack sker detta vid pop från navigationsstacken. För ett modalt fönster — vid stängning. För TabView — vid byte av flik, om View inte cachas.

Hur skickar jag parametrar till @StateObject vid initiering?

Använd en anpassad init med åtkomst till property wrappern via understreck: _viewModel = StateObject(wrappedValue: MyViewModel(param: value)). Detta mönster gör det möjligt att skicka alla parametrar till ObservableObject samtidigt som garantin för engångsskapande av objektet under Viewns livstid behålls.

Sammanfattning

  • @StateObject — property wrapper för att skapa och äga ObservableObject inuti View, tillgängligt från iOS 14.
  • Garanti för engångsskapande — objektet initieras en gång och återskapas inte vid ombyggnad av View.
  • Source of truth — @StateObject är sanningskällan, @ObservedObject är bara observatören.
  • Livscykel — objektet lever så länge View finns i SwiftUI-hierarkin och förstörs när det lämnar den.
  • Initiering med parametrar — kräver åtkomst till property wrappern via _viewModel och StateObject(wrappedValue:).
  • Ägandemisstag — att använda @ObservedObject för att skapa ett objekt leder till dataförlust vid ombyggnad.
  • Ett objekt — en @StateObject — för delad data, skapa @StateObject i rot-View och skicka till underordnade via @ObservedObject.

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

Diskutera projektet

Läs också