Az @State egy Property Wrapper a SwiftUI-ban a lokális állapot kezelésére egyetlen nézeten belül. A SwiftUI automatikusan újrarajzolja a nézetet minden @State tulajdonság változásakor, így a felület reaktívvá válik kézi frissítési hívások nélkül. A Apple Developer Documentation (2025) szerint az @State egyszerű típusokhoz és egy nézethez tartozó struktúrákhoz ajánlott. @State a legegyszerűbb módja az interaktivitás hozzáadásának egy SwiftUI-felülethez.
Főbb pontok
@State egy beépített Property Wrapper a SwiftUI-ban, amely lehetővé teszi egy nézet számára saját állapotának tárolását és nyomon követését. Amikor az @State értéke megváltozik, a SwiftUI automatikusan újrarajzolja a nézetet, újra meghívva a body tulajdonságot. Ez a reaktív programozás alapja a SwiftUI-ban: a fejlesztő deklarálja az állapotot, a keretrendszer pedig gondoskodik a felület szinkronizálásáról.
Az @State egy, a SwiftUI által kezelt tárolóterületet hoz létre a kupacon. Ez a terület perzisztens — túléli a nézetstruktúra ismételt inicializálásait, amelyek minden rendereléskor bekövetkeznek. A SwiftUI a nézet azonosítóját (a hierarchiában elfoglalt pozíció alapján generálva) használja az @State tulajdonság egy adott nézethez kötéséhez. Ennek köszönhetően az állapot nem állítódik vissza a szülőnézet frissítésekor.
Fontos korlátozás: az @State csak értéktípusokhoz (struktúrák, felsorolások, primitívek) készült. Referenciatípusokhoz (osztályok) használjon @StateObject vagy @ObservedObject. Ha egy osztályt rendel egy @State tulajdonsághoz, a SwiftUI nem fogja tudni észlelni az objektumon belüli változásokat — csak a teljes referenciacsere.
A SwiftUI az @State-et a belső Storage mechanizmuson keresztül valósítja meg. Minden @State tulajdonság egy dedikált memóriacellát kap, amely a nézet speciális tárolókonténerében található. Amikor írás történik a wrappedValue-ba, a SwiftUI a didSet-en keresztül értesíti függőségi gráfját (dependency graph) az újrarajzolás szükségességéről.
struct ContentView: View {
@State private var name: String = "User"
@State private var isLoggedIn: Bool = false
var body: some View {
VStack {
Text("Szia, \(name)")
Button(isLoggedIn ? "Kijelentkezés" : "Bejelentkezés") {
isLoggedIn.toggle()
}
}
}
}
A példában két @State tulajdonság van: name (String) és isLoggedIn (Bool). Az isLoggedIn.toggle() meghívásakor a SwiftUI megjelöli a ContentView-t frissítést igénylőként, és a következő renderelési ciklusban újraindítja a body-t. Kulcsfontosságú pont: az @State tulajdonságokat mindig a private módosítóval deklaráljuk — ez azt jelzi, hogy az állapot kizárólag az aktuális nézethez tartozik, és nem szabad kívülről közvetlenül módosítani.
A változások megfigyeléséhez a SwiftUI a Combine-ból származó CurrentValueSubject-et használja. Minden @State tulajdonság létrehoz egy rejtett kiadót, amely minden változáskor értesíti a rendszert. Ez lehetővé teszi a SwiftUI számára, hogy csak a minimálisan szükséges nézetkészletet rajzolja újra, elkerülve a hierarchia teljes frissítését.
Az @State egyszerű lokális állapotokhoz optimális: kereső szövegmezők, logikai jelzők modális ablakokhoz, beállítási kapcsolók, számlálók, kiválasztott listaelemek. Ha az értéket csak egy nézetben és annak beágyazott komponenseiben (@Binding-en keresztül) használják, az @State a megfelelő választás. Olyan állapotokhoz, amelyeknek túl kell élniük a nézet bezárását (pl. űrlapadatok), az @State szintén alkalmas, amíg a nézet a hierarchiában marad.
Ne használja az @State-et globális alkalmazásállapotokhoz, hálózati adatok gyorsítótárazásához vagy több képernyőn használt objektumokhoz. Ezekre a célokra az @StateObject és az @EnvironmentObject szolgál. Az @State szintén nem alkalmas nagy mennyiségű adat tárolására — minden változáskor a teljes nézet újrarajzolásra kerül.
@Binding egy híd a szülőnézetben lévő @State és a gyermeknézet között, amelynek módosítania kell ezt az állapotot. A szülő deklarálja az @State-et, a gyermekkomponens pedig a $ projekción keresztül kapja meg a Binding-et. A Binding módosítása a gyermeknézetben automatikusan frissíti az @State-et a szülőben — és fordítva. Ez egyirányú adatáramlást biztosít visszacsatolási lehetőséggel.
struct ParentView: View {
@State private var text: String = ""
var body: some View {
ChildView(text: $text)
}
}
struct ChildView: View {
@Binding var text: String
var body: some View {
TextField("Enter text", text: $text)
}
}
A listában a ParentView birtokolja az @State text-et, a ChildView pedig $text-et kap Binding-ként. A ChildView-on belüli TextField a text: $text-en keresztül kötődik ehhez a Binding-hez. Amikor a felhasználó gépel a TextField-ben, az érték a ChildView-ban változik a Binding-en keresztül, ami frissíti az @State-et a ParentView-ban. Mindkét nézet újrarajzolódik az új értékkel.
A leggyakoribb hiba — osztály hozzárendelése egy @State tulajdonsághoz. Ha @State var model = MyClass()-t ír, a SwiftUI nem tudja nyomon követni a tulajdonságok változásait az osztályon belül — csak magának az objektumnak a cseréjét. Osztályokhoz mindig használjon @StateObject-öt. A második gyakori probléma — az @State deklarálása private módosító nélkül, ami megsérti az állapot enkapszulációjának elvét.
@State közvetlen átadása a gyermeknézetnek $ nélkül — egy másik tipikus hiba. Ha TextField(text: $text) helyett TextField(text: text)-et ad át, a gyermekkomponens egy egyszerű stringet kap, nem Binding-et. A szöveg változása a TextField-ben nem lesz szinkronizálva a szülő @State-tel. Mindig használja a $ projekciót a Binding átadásához.
A harmadik hiba — több @State tulajdonság kapcsolódó adatokhoz. Ha több érték logikailag egy egészet alkot (pl. űrlapmezők), egyesítse őket egyetlen struktúrában egy @State-tel. Ez leegyszerűsíti az állapot átadását a gyermeknézeteknek és csökkenti a különálló frissítési triggerek számát.
@State a legtöbb SwiftUI-projektben használatos az alapvető interaktivitáshoz. Vizsgáljunk meg egy bejelentkezési űrlap példát, ahol az @State kezeli a szövegmezőket és a betöltési állapotot. Ez a minta minden alkalmazásban megtalálható — az egyszerű jegyzetektől a bonyolult vállalati megoldásokig.
struct LoginView: View {
@State private var email: String = ""
@State private var password: String = ""
@State private var isLoading: Bool = false
@State private var errorMessage: String?
var body: some View {
Form {
TextField("Email", text: $email)
SecureField("Password", text: $password)
Button("Bejelentkezés") {
login()
}.disabled(isLoading)
}
}
private func login() {
isLoading = true
// Hálózati kérés végrehajtása
}
}
A példában négy @State tulajdonság van: email és password az űrlapmezőkhöz, isLoading a betöltés jelzéséhez és errorMessage a hibák megjelenítéséhez. Minden tulajdonság függetlenül kezeli a felület saját részét. Amikor az isLoading változik, a gomb automatikusan blokkolódik a disabled(isLoading) révén — kézi UI-frissítés nélkül.
Gyakran ismételt kérdések
@State egy adott nézet lokális állapotára szolgál. A private módosító garantálja, hogy más komponensek ne módosíthassák közvetlenül, megsértve az enkapszulációt. Külső hozzáféréshez használja a $ projekciót.
Igen, az @State támogatja a tömböket és szótárakat, mivel ezek értéktípusok. Azonban egy tömb elem megváltoztatásakor a SwiftUI a teljes nézetet újrarajzolja. Nagy listákhoz hatékonyabb az @StateObject használata @Published-tel.
@State helyesen működik az Optional típusokkal. Nil hozzárendelésekor a SwiftUI érzékeli a változást és újrarajzolja a nézetet. Ez kényelmes olyan állapotokhoz, mint az errorMessage: String?, ahol a nil a hiba hiányát jelenti.
@State megtartja az értéket, amíg a nézet a hierarchiában marad. Ha a nézetet eltávolítják a hierarchiából és újra hozzáadják, az @State újrainicializálódik az alapértelmezett értékkel. Perzisztenciához használjon @AppStorage-öt.
Igen, csomagolja a változást withAnimation-be: withAnimation(.easeInOut) { isExpanded.toggle() }. A SwiftUI animálja az átmenetet a felület régi és új állapota között a megadott animációs típussal.
Összefoglalás
Kulcsraké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