@State је Property Wrapper у SwiftUI-ју за управљање локалним стањем унутар једног приказа. SwiftUI аутоматски прецртава приказ при свакој промени @State својства, чинећи интерфејс реактивним без ручних позива за ажурирање. Према Apple Developer Documentation (2025), @State се препоручује за једноставне типове и структуре које припадају једном приказу. @State је најједноставнији начин да додате интерактивност SwiftUI интерфејсу.
Главно
@State је Property Wrapper уграђен у SwiftUI који омогућава приказу да складишти и прати сопствено стање. Када се вредност @State промени, SwiftUI аутоматски прецртава приказ, поново позивајући својство body. Ово је основа реактивног програмирања у SwiftUI-ју: програмер декларише стање, а оквир преузима синхронизацију интерфејса.
@State ствара област за складиштење на хрпи којом управља SwiftUI. Ова област је перзистентна — преживљава поновне иницијализације структуре приказа које се дешавају при сваком рендеровању. SwiftUI користи идентификатор приказа (генерисан на основу позиције у хијерархији) за повезивање @State својства са одређеним приказом. Захваљујући томе, стање се не ресетује при ажурирању родитељског приказа.
Важно ограничење: @State је намењен само за вредносне типове (структуре, набрајања, примитиве). За референцне типове (класе) користите @StateObject или @ObservedObject. Ако доделите класу @State својству, SwiftUI неће моћи да открије промене унутар објекта — само замену референце у целини.
SwiftUI имплементира @State кроз унутрашњи механизам Storage. Свако @State својство добија наменску меморијску ћелију која се чува у посебном storage контејнеру приказа. Када дође до уписа у wrappedValue, SwiftUI преко didSet обавештава свој граф зависности (dependency graph) о потреби за прецртавањем.
struct ContentView: View {
@State private var name: String = "User"
@State private var isLoggedIn: Bool = false
var body: some View {
VStack {
Text("Здраво, \(name)")
Button(isLoggedIn ? "Одјава" : "Пријава") {
isLoggedIn.toggle()
}
}
}
}
У примеру су два @State својства: name (String) и isLoggedIn (Bool). При позиву isLoggedIn.toggle(), SwiftUI означава ContentView као захтеван за ажурирање и поново покреће body у следећем циклусу рендеровања. Кључна тачка: @State својства се увек декларишу са модификатором private — то је сигнал да стање припада искључиво тренутном приказу и не треба да се мења споља директно.
За посматрање промена, SwiftUI користи CurrentValueSubject из Combine-а. Свако @State својство ствара скривеног издавача који обавештава систем при свакој промени. Ово омогућава SwiftUI-ју да прецртава само минимално неопходан скуп приказа, избегавајући потпуно ажурирање хијерархије.
@State је оптималан за једноставна локална стања: текстуална поља за претрагу, булове заставице за модалне прозоре, прекидачи подешавања, бројачи, изабрани елементи листе. Ако се вредност користи само у једном приказу и његовим угњежденим компонентама (путем @Binding), @State је прави избор. За стања која треба да преживе затварање приказа (нпр. подаци форме), @State је такође погодан, док приказ остаје у хијерархији.
Не користите @State за глобална стања апликације, кеширање мрежних података или објеката који се користе на више екрана. За ове намене су намењени @StateObject и @EnvironmentObject. Такође, @State није погодан за складиштење великих количина података — сваки пут када се промени, цео приказ ће бити прецртан.
@Binding је мост између @State у родитељском приказу и дечјем приказу који треба да мења ово стање. Родитељ декларише @State, а дечја компонента добија Binding кроз пројекцију $. Промена Binding-а у дечјем приказу аутоматски ажурира @State код родитеља — и обрнуто. Ово обезбеђује једносмерни ток података са могућношћу повратне спреге.
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)
}
}
У листингу, ParentView поседује @State text, а ChildView прима $text као Binding. TextField унутар ChildView-а се везује за овај Binding преко text: $text. Када корисник куца у TextField-у, вредност се мења у ChildView-у кроз Binding, што изазива ажурирање @State у ParentView-у. Оба приказа се прецртавају са новом вредношћу.
Најчешћа грешка — додељивање класе @State својству. Ако напишете @State var model = MyClass(), SwiftUI неће моћи да прати промене својстава унутар класе — само замену самог објекта. За класе увек користите @StateObject. Други уобичајени проблем — декларисање @State без модификатора private, што нарушава принцип инкапсулације стања.
Директно прослеђивање @State дечјем приказу без $ — још једна типична грешка. Ако проследите TextField(text: text) уместо TextField(text: $text), дечја компонента ће добити обичан стринг, а не Binding. Промена текста у TextField-у неће бити синхронизована са родитељским @State. Увек користите пројекцију $ за прослеђивање Binding-а.
Трећа грешка — вишеструка @State својства за повезане податке. Ако неколико вредности логички чине једну целину (нпр. поља форме), спојите их у једну структуру са једним @State. Ово поједностављује прослеђивање стања дечјим приказима и смањује број одвојених окидача за ажурирање.
@State се користи у већини SwiftUI пројеката за основну интерактивност. Размотримо пример форме за пријаву, где @State управља текстуалним пољима и стањем учитавања. Овај образац се среће у свакој апликацији — од једноставних белешки до сложених корпоративних решења.
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("Пријава") {
login()
}.disabled(isLoading)
}
}
private func login() {
isLoading = true
// Изврши мрежни захтев
}
}
У примеру су четири @State својства: email и password за поља форме, isLoading за индикацију учитавања и errorMessage за приказивање грешака. Свако својство независно управља својим делом интерфејса. При промени isLoading, дугме се аутоматски блокира кроз disabled(isLoading) — без ручног ажурирања UI-ја.
Често постављана питања
@State је намењен за локално стање одређеног приказа. Модификатор private гарантује да друге компоненте не могу директно да га мењају, нарушавајући инкапсулацију. За спољни приступ користите пројекцију $.
Да, @State подржава низове и речнике, јер су то вредносни типови. Међутим, при промени елемента низа SwiftUI прецртава цео приказ. За велике листе ефикасније је користити @StateObject са @Published.
@State исправно ради са Optional типовима. При додељиванию nil, SwiftUI открива промену и прецртава приказ. Ово је згодно за стања попут errorMessage: String?, где nil значи одсуство грешке.
@State чува вредност док приказ остаје у хијерархији. Ако се приказ уклони из хијерархије и поново дода, @State се иницијализује изнова са подразумеваном вредношћу. За перзистентност користите @AppStorage.
Да, умотајте промену у withAnimation: withAnimation(.easeInOut) { isExpanded.toggle() }. SwiftUI анимира прелаз између старог и новог стања интерфејса са наведеним типом анимације.
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође