[SwiftUI] State , Binding

오늘은 SwiftUI 중에서 propertyWrapper 로 사용되는 것들 중 가장 기초가 되는 State, Binding에 대해서 다시 한번 정리할 겸 글을 작성해보려고 한다.

 

State

먼저 SwiftUI에서 State는 뷰의 상태를 관리하는데 사용된다. 뷰 내부에서만 사용되는 상태이며, 상태가 변경되면 해당 상태를 사용하는 뷰가 다시 렌더링 된다.

 

보통 뷰의 로컬 상태를 관리하는데 사용되며 private를 사용하고 뷰의 최상단에서 관리되어야 한다.

이로 인해서 상태 관리가 뷰 내부에 캡슐화 되어 더욱 안전하게 관리 될 수 있게 된다.

 

예제코드로 살펴보자

struct StateBasic: View {
    @State var backgroundColor: Color = Color.green
    @State var myTitle: String = "아직 버튼 안눌림"
    @State var count: Int = 0
    
    var body: some View {
        ZStack{
            backgroundColor
                .ignoresSafeArea()
            
            VStack (spacing: 20) {
                Text(myTitle)
                    .font(.title)
                Text("카운트 \\(count)")
                
                HStack (spacing: 20) {
                    Button(action: {
                        backgroundColor = .red
                        myTitle = "1번 버튼 눌림"
                        count += 1
                    }, label: {
                        Text("1번 버튼")
                    })
                    
                    Button(action: {
                        backgroundColor = .yellow
                        myTitle = "2번 버튼 눌림"
                        count -= 1
                    }, label: {
                        Text("2번 버튼")
                    })
                }
            }
            .foregroundColor(.white)
        }
    }
}

이 예제는 뷰 내 카운트를 올리고 내릴 수 있도록 구현한 코드이다. backgroundColor, myTitle, count는 이 후 버튼을 눌러 변경되어야 하는 값이기 때문에 @State 를 활용해 변수를 지정해 준다.

State로 지정해주었기 때문에 하단에 버튼을 눌러 값을 변경하는 코드를 넣어주면 이렇게 배경색과 카운트, 그리고 타이틀 문구가 변경되어도 잘 적용되는 것을 볼 수 있다.

 

Binding

Binding은 부모 뷰에서 전달된 상태를 자식 뷰에서 읽고 쓸 수 있도록 한다. 이를 통해서 두 뷰 간의 상태 공유가 가능해질 수 있다. 여러 뷰에서 동기화가 가능하다는 말이다!

struct BindingBasic: View {
    
    @State var backgroundColor: Color = Color.green
    @State var title:String = "Binding Basic View"
    
    var body: some View {
        ZStack {
            backgroundColor
                .ignoresSafeArea()
            
            VStack {
                Text(title)
                
                BindingChildBasic(backgroundColor: $backgroundColor, title: $title)
            }
        }
    }
}

먼저 부모뷰에 값이 변경되어야 하는 변수들을 @State을 통해 지정해 준다.

struct BindingChildBasic: View {
    
    @State var buttonColor: Color = Color.blue
    @Binding var backgroundColor: Color
    @Binding var title: String
    
    var body: some View {
        Button(action: {
            backgroundColor = .orange
            buttonColor = Color.pink
            title = "Binding Child View"
        }, label: {
            Text("ChildView 이동")
                .foregroundColor(.white)
                .padding(10)
                .padding(.horizontal, 20)
                .background(
                    Color.blue
                )
                .cornerRadius(10)
        })
    }
}

그 다음 차일드 뷰를 하나 만들어 주고 해당 내용에서 부모뷰에서 사용되는 변수의 값을 사용해야 한다면 Binding을 활용 할 수 있다는 것이 핵심이다!

 

보면 현재 부모뷰에서 가지고 있는 backgroundColor와 title이 차일드뷰에서 값이 변경되어야 하므로 동일하게 사용하고 해당 내용이 부모뷰와 연결될 수 있도록 Binding을 해준 상태이다.

 

이렇게 되면 차일드 뷰에서 backgroundColor, title의 값을 변경해주고 이를 부모뷰에 적용되도록 한다.

VStack {
    Text(title)
    
    BindingChildBasic(backgroundColor: $backgroundColor, title: $title)
}

다시 부모 뷰로 넘어와서 위에 작성했던 차일드 뷰의 내용을 적용하기 위해 그대로 넣어준 뒤 부모뷰에서 이 변수를 직접 지정을 해줘야 사용이 가능하다!

지정해주는 법은 ‘ $ ‘ 를 해당 내용앞에 붙여 차일드뷰와 부모뷰의 상태를 동기화 시켜야 완성 된다!

 

이렇게 오늘은 State , Binding 에 대해서 정리하는 시간을 가졌다 ㅎㅎ 매우 기초적인 내용이지만 한번 더 제대로 정리하기 위해 글로 작성해봤다!

 

다음에는 조금 더 복잡한 propertyWrapper에 대해서 다뤄볼 예정이다 ( @ObservedObject 등등 )

오늘은 여기까지!!