[iOS] SwiftUI - @State, @Binding

nnnyeong·2022년 3월 23일
2

iOS

목록 보기
9/17

SwiftUI 와 mvvm 을 경험하면서 정말 덕을 톡톡히 본 두가지 Property Wrapper 에 대해 정리해보자!




State

UIKit 을 사용했을 때는 어떠한 변수에 변화가 생기면 해당 변화를 직접 관찰하고 반영 해 주어야 했는데 SwiftUI 에서는 property wrapper 를 활용해 이러한 작업을 자동화 할 수 있도록 했다.

  • 변화가 생기면 해당 변수의 값을 읽거나 새로 쓸 수 있음을 의미하는 property wrapper
  • SwiftUI 는 state 로 선언된 property 들의 저장소를 관리
  • State value 값이 변경되면 뷰는 해당 value 의 appearance 를 무효화 하고 다시 body 값을 계산
  • state 변수값이 변경되면 view 를 다시 랜더링 하기 때문에 항상 최신 값을 가짐
  • State 인스턴스는 그 자체로 값이 아닌, 값을 읽고 쓰는 것을 의미함
  • 현재 뷰 UI의 특정 상태를 저장하기 귀해 만들어진 것이기 때문에 보통 private
  • @State 속성으로 어떤 프로퍼티의 초기값을 지정했다면, 다른 값으로 재할당 불가, @Binding 변수를 통해서만 가능


Binding

@State 로 선언된 속성을 다른 뷰에서 사용하려 한다면 @Binding 을 사용해 줄 수 있다. 사용시에는 앞에 $를 사용해 Bining 변수임을 나타낸다. @State 로 선언된 속성에 변경이 생기면 @Binding 변수에서 이를 인지하고 해당 값에 따른 뷰 변화를 바로 반영할 수 있도록 하는 방식이다.

  • 다른 뷰에서 @State 속성으로 선언된 프로퍼티를 사용한다면 @Binding 속성을 사용
  • 사용시에는 $를 앞에 붙여 binding 변수임을 나타냄
  • 외부에서 접근해야 하기 때문에 private X



예시

숫자를 하나씩 높이고 하나의 sheet 를 열어 해당 변화가 적용 되는지를 확인하는 간단한 앱을 통해 적용해 보자!

먼저 결과부터 보자면,


첫view

struct ContentView: View {
    
    @State var presenting = false
    @State private var number : Int = 167
    
    var body: some View {
        VStack {
            Text("Number is \(number)")
                .fontWeight(.semibold)
                .font(.system(size: 30))
                .padding(.bottom, 20)
            
            Button(action: {
                self.number += 1
            }, label: {
                Text("Add")
                    .foregroundColor(.white)
                    .font(.system(size: 25))
                    .fontWeight(.bold)
                    .padding(10)
            })
                .background(Color.green)
                .padding(50)
            
            Button(action: {
                self.presenting = true
            }, label: {
                Text("Move to Check")
                    .foregroundColor(.white)
                    .font(.system(size: 25))
                    .fontWeight(.bold)
                    .padding(10)
            })
                .background(Color.blue)
                .padding(50)
                .sheet(isPresented: self.$presenting){
                    DetailView(number:
                                self.$number)
                }
            
            
        }
    }
}


확인view

struct DetailView: View {
    @Binding var number : Int
    
    var body: some View {
        Text("Number : \(number)")
    }
}


@State 로 선언한 속성 number 의 값이 변하면 해당 변화가 DeatilView 에서 @Binding 되어 자연스레 뷰에 반영되는 것을 확인 할 수 있다!

profile
주니어 개발자까지 ☄️☄️

2개의 댓글

comment-user-thumbnail
2022년 11월 30일

number가 private이 맞나요? 외부 뷰에서 사용한다고 설명되어있는데... 제가 코린이라 여쭤봅니다.

1개의 답글