[SwiftUI] @State, @Binding 프로퍼티 래퍼를 사용하는 이유와 예제 코드
상태 프로퍼티
상태 프로퍼티(state property)는 상태에 대한 가장 기본적인 형태이며, 뷰 레이아웃의 현재 상태(예를 들어, 토글 버튼이 활성화되었는지 여부, 텍스트 필드에 입력된 텍스트, 또는 피커 뷰에서의 현재 선택)를 저장하기 위해서만 사용된다. 상태 프로퍼티는 String이나 Int 값처럼 간단한 데이터 타입을 저장하기 위해 사용되며, @State 프로퍼티 래퍼를 사용하여 선언된다.
struct ContentView: View {
@State private var wifiEnabled = true
@State private var userName = ""
var body: some View {
.
.
상태 값은 해당 뷰에 속한 것이기 때문에 private 프로퍼티로 선언되어야 한다.
상태 프로퍼티 값이 변경되었다는 것은 그 프로퍼티가 선언된 뷰 계층구조를 다시 렌더링 해야한다는 SwiftUI 신호다.
프로퍼티를 선언했다면 레이아웃에 있는 뷰와 바인딩을 할 수 있다. 바인딩이 되어 있는 뷰에서 어떤 변경이 일어나면 해당 상태 프로퍼티에 자동으로 반영된다.
상태 프로퍼티와의 바인딩은 프로퍼티 이름 앞에 ‘$’를 붙이면 된다
struct ContentView: View {
@State private var wifiEnabled = true
@State private var userName = ""
var body: some View {
VStack {
TextField("Enter user name", text: $userName)
}
}
}
var body: some View {
VStack {
Toggle(isOn: $wifiEnabled) {
Text("Enable Wi-Fi")
}
TextField("Enter user name", text: $userName)
Text(userName)
Image(systemName: wifiEnabled ? "wifi" : "wifi.slash")
}
}
상태 바인딩
상태 프로퍼티는 선언된 뷰와 그 하위 뷰에 대한 현재 값이다. 하지만, 어떤 뷰가 하나 이상의 하위 뷰를 가지고 있으며 동일한 상태 프로퍼티에 대해 접근해야 하는 경우가 발생한다. 예를 들어, 앞의 예제에 있는 와이파이 이미지 뷰가 하위 뷰로 분리되는 상황을 살펴보자.
VStack {
Toggle(isOn: $wifiEnabled) {
Text("Enable WiFi")
}
TextField("Enter user name", text: $userName)
WifiImageView()
}
struct WifiImageView: View {
var body: some View {
Image(systemName: wifiEnabled ? "wifi" : "wifi.slash")
}
}
wifiImageView 하위 뷰는 여전히 wifiEnabled 상태 프로퍼티에 접근해야 한다. 하지만, 분리된 하위 뷰의 요소인 Image 뷰는 이제 메인 뷰의 범위 밖이다.
다시 말해, WifiImageView 입장에서 보면 WifiImageView에 있는 wifiEnabled 프로퍼티는 정의되지 않은 변수인 것이다.
이 문제는 다음과 같이 @Binding 프로퍼티 래퍼를 이용하여 프로퍼티를 선언하면 해결된다.
struct WifiImageView: View {
@Binding var wifiEnabled : Bool
var body: some View {
Image(systemName: wifiEnabled ? "wifi" : "wifi.slash")
}
}
이제 하위 뷰가 호출될 때 상태 프로퍼티에 대한 바인딩을 전달하면 된다.
WifiImageView(wifiEnabled: $wifiEnabled)
-알라딘 eBook <핵심만 골라 배우는 SwiftUI 기반의 iOS 프로그래밍> (닐 스미스 지음, 황반석 옮김) 중에서