@State은 View 안에서 View를 표시하기 위해서 사용되는 변수에 붙여줍니다. 즉 해당 변수가 바뀌면 View도 갱신되어야 하는 변수에 붙여주는 것입니다.
물론 @State로 선언하지 않아도 View에 표시할 수 있습니다.
import SwiftUI
struct ContentView: View {
var name = "Kim"
var body: some View {
Text(name)
}
}
하지만 이런 경우에 해당 변수를 변경하면 Text라는 View에 반영되지 않고 에러가 나게 됩니다.
따라서 변수가 바뀔 때 View에 업데이트가 되기를 원한다면 @State를 붙여서 선언해줍시다. 아래 처럼 하면 버튼을 통해서 name 변수에 새로운 String을 할당할 수 있고 Text라는 View에 반영할 수 있습니다.
import SwiftUI
struct ContentView: View {
@State var name = "Kim"
var body: some View {
VStack{
Text(name)
Button("Change Name", action: {
name = "Lee"
})
}
}
}
Binding 변수는 어떤 뷰의 변수를 다른 뷰의 변수와 연결할 때 사용합니다. (by 참조 값을 공유) 즉 하나의 값이 변경될 때 복수의 뷰가 바뀌어야 한다면 Binding 변수를 사용해야합니다. Binding 변수는 State와 마찬가지로 변경되는 경우에 View에 반영됩니다.
@Binding은 하위 뷰가 상위 뷰에 바뀐 값을 전달할 때 사용합니다. 즉 데이터가 아래서 위 뿐만이 아니라 아래에서 위로 올라올 수도 있는 경우에 사용합니다.
먼저 상위 View가 @State로 변수를 가지고 있고 그 변수를 하위 View에 Binding로 전달합니다.
그리고 하위 View에서 Binding 변수를 바꾸게 되면 Binding 되어 있는 상위 View의 State 변수가 변하면서 Text도 re-render 됩니다.
State 변수와는 다르게 Binding 변수는 초기값을 가지고 있을 수 없는데 그 이유는 Binding 변수는 연결하는 기능만을 할 뿐 실제로 값을 가지고 있는 변수는 상위 뷰의 State이기 때문입니다.
import SwiftUI
struct ContentView: View {
@State private var stateBool = false
var body: some View {
VStack {
Text(String(describing: stateBool))
SomeButton(someBool: $stateBool)
}
}
}
struct SomeButton: View {
@Binding var bindingBool: Bool
var body: some View {
Button(action: {
bindingBool.toggle()
}, label: {
Text("boolean 값 토글")
})
}
}