k-coding
SwiftUI @State, @Binding 본문
SwiftUI @State, @Binding
SwiftUI에서는 처음 생성할때도 그렇고 기본적으로 구조체에서 View를 구현합니다.
그런데 원래 구조체에서는 변수값을 변경할 수 없다고 배웠었는데요..?
그렇다면 SwiftUI에서는 변수를 설정하면 값을 바꿀수 없는걸까요?
원래 UIkit에서는 구조체에서 변수를 변경할 때 mutating을 사용해주었는데요.
View 프로토콜의 body는 { get }으로 되어 있으며, nonmutating 구현을 요구합니다.
따라서 SwiftUI에서는 구조체안에서 변수를 바꿀때 @State를 사용하게 됩니다.
@State ( 상태 프로퍼티 )
@State는 현재 상태를 나타내는 속성으로써 View의 어떤 값을 저장하는 데 사용합니다.
예를 들어 String, Int, Boolean등 간단한 데이터 타입을 저장하며
상태 값은 해당 뷰에 속한 것이기 때문에 Private프로퍼티로 선언되어야 합니다.
struct ContentView: View {
@State private var isOn = true
@State private var name = ""
}
상태 프로퍼티 값이 변경 되었단 말은 해당 프로퍼티가 선언된 뷰 계층구조를 다시 rendering해야 한다는 말로
계층구조 안에 있는 모든 뷰를 재 생성하고 표시해야합니다.
결국 값이 바뀌는 프로퍼티에 의존하는 뷰들은 모두 최신 값이 반영된 값으로 업데이트 됩니다.
상태 프로퍼티를 선언하면 레이아웃에 있는 뷰와 바인딩 할 수 있게되는데
바인딩 된 뷰에서는 어떤 값의 변경이 발생하면 해당 상태 프로퍼티를 자동으로 업데이트 해줍니다.
바인딩은 프로퍼티 앞에 $를 붙여주면됩니다.
struct ContentView: View {
@State private var isOn = true
@State private var name = ""
var body : some View {
VStack {
TextField("이름을 입력해 주십시오.", text: $name)
.multilineTextAlignment(.center)
.font(.largeTitle)
.foregroundColor(.black)
Text("이름은 : \(name)")
.fontWeight(.bold)
.foregroundColor(.black)
}
}
}
위 코드에서 보셔야 할 점이 TextField에서는 name이라는 변수를 받기위해 $ 를 사용했지만,
Text에서는 $ 없이 그냥 name만 사용되었다.
이유는 TextField에서 $name을 통하여 상태 프로퍼티에 할당된 값을 변경없이 사용하기 때문입니다.
항상 $ 붙이는게 아니라는 점 !!
@Binding
@Binding은 하위 뷰에서 상위 뷰에 선언된 상태프로퍼티에 접근할 수 있게 해줍니다.
예를들어 아래와 같은 하위 뷰가 추가되었다고 생각해봅시다.
struct NameView: View {
var body: some View {
Text("반갑습니다. \(name)님")
.fontWeight(.bold)
.foregroundColor(.black)
.font(.system(size: 60))
}
}
위~에 작성했던 소스를 참고하시면 거기서 상태 프로퍼티로 name을 사용한것을 이 뷰에서도 재사용하는것을 눈치챌 수 있습니다.
근데 이렇게만 작성하면 바로 에러가 등장하게됩니다! 또잉..
NameView의 Text는 계속 name 상태프로퍼티에 접근해야하지만, 이제 메인뷰의 범위 밖으로 벗어나버렸기 때문입니다.
따라서 NameView입장에서는 name은 정의되어있지않은 변수인 것이죠.
이러한 문제를 해결해주는것이 @Binding입니다.
@Binding var name : String
다음과 같은 형식으로 하위 뷰가 호출 될 때 상태 프로퍼티에 대한 바인딩을 전달하면 됩니다.
struct ContentView: View {
@State private var isOn = true
@State private var name = ""
var body : some View {
VStack {
TextField("이름을 입력해 주십시오.", text: $name)
.multilineTextAlignment(.center)
.font(.largeTitle)
.foregroundColor(.black)
Text("이름은 : \(name)")
.fontWeight(.bold)
.foregroundColor(.black)
}
}
}
struct NameView: View {
@Binding var name: String
var body: some View {
Text("반갑습니다. \(name)님")
.fontWeight(.bold)
.foregroundColor(.black)
.font(.system(size: 60))
}
}
'iOS > Swift UI' 카테고리의 다른 글
SwiftUI Divider, Spacer (0) | 2022.05.05 |
---|---|
SwiftUI WebView (UIViewRepresentable) (0) | 2022.05.05 |
SwiftUI Navigation 연결 (0) | 2022.05.01 |
SwiftUI (HStack / VStack) (0) | 2022.05.01 |
SwiftUI 알아보기 (0) | 2022.04.30 |