본문 바로가기

학습 노트/Swift UI (2022)

23. State & Binding

UIKit

SwiftUI

UIKit과 SwiftUI의 가장 큰 차이점은 View(UI)를 직접 업데이트하지 않는다는 점이다.
SwiftUI에서 View는 상태(State)에 자동으로 반응한다.

이러한 상태를 나타내는 변수를 Property Wrapper 라고 부르며 자주 사용되는 것들은 다음과 같다.

  • State
  • Binding
  • Environment
  • ObservedObject
  • EnvironmentObject
  • StateObject
 

All SwiftUI property wrappers explained and compared - a free SwiftUI by Example tutorial

Was this page useful? Let us know! 1 2 3 4 5

www.hackingwithswift.com

외에도 여러 PropertyWrapper가 존재한다.

 

@State


 

Apple Developer Documentation

 

developer.apple.com

해당 값이 바뀔 때 마다 View가 업데이트된다.
View의 상태를 저장하기 때문에 해당 변수의 주체는 소유한 View여야 한다.

One Way Connection

struct OneWayConnection: View {
   var text: String = "Hello"
   
   var body: some View {
      VStack(spacing: 70) {
         Text(text)
            .font(.largeTitle)
      }
   }
}

예를 들어 Text 자체는 는 항상 문자열을 받지만 스스로 이를 변경할 수는 없다.
즉, 파라미터로 전달된 속성에 의지한다. 이를 one way connection이라고 한다.

일반 변수는 Self에 해당하는 OneWatConnection View가 구조체(Struct)이기 때문에 불변에 해당한다.
메서드는 mutating 키워드가 존재하지만 이를 선언할 블록이 Computed Property인 body이기 때문에 사용할 수 없다.

즉 State 없이는 구조체와 연관된 메모리에 속성을 저장하므로 읽기 전용이 된다.
State를 사용하면 구조체와 별개의 공간에 속성을 저장하므로 읽기와 쓰기 모두가 가능해진다.

 

@Binding


다른 View에서 상태를 저장하거나 사용할 수 있도록 한다.

struct TwoWayConnection: View {
   @State var value: String = "Hello"
   
   var body: some View {
      VStack(spacing: 70) {
		  TextField("type here", text: $value)
			  .padding()
                  
         Button(action: {
            value = "trans!"
         }, label: {
            Text("Update")
         })
         .padding()
      }
   }
}

간혹 View의 파라미터로 binding을 요구하기도 하는데,
이 경우 변수를 State Variable로 선언하고, 사용 시 '$'를 변수명 앞에 붙여 사용한다.

import SwiftUI
import Combine

struct TwoWayConnection: View {
   @State var value: String = ""
   @State var typeState = false

   var body: some View {
      VStack(spacing: 70) {
          TextField("type here", text: $value)
              .padding()
              .onReceive(Just(value)) { value in
                  if value.count > 0 {
                      typeState = true
                  } else {
                      typeState = false
                  }
              }

         Button(action: {
            value = "trans!"
         }, label: {
            Text("Update")
         })
         .padding()
      }
      .toolbar {
          ToolbarItemGroup(placement: .bottomBar) {
              SubView(typeState: $typeState)
          }
      }
   }
}

struct SubView: View {
    @Binding var typeState: Bool

    var body: some View {
        HStack {
            Button {
            } label: {
                Text("reset")
            }
            .foregroundColor(.red)

            Spacer()

            Button {
            } label: {
                Text("Next")
            }
            .disabled(!typeState)
        }
    }
}

속성과 View가 양방향으로 연결되고, 항상 최신 값을 유지할 수 있다.

TwoWayConnection View의 State Variable인 typeState를
SubView에서 잘 Binding 해 하단 toolbar의 버튼의 상태를 함께 조작하고 있다.
만약 이러한 방식으로 속성을 여러 View가 공용으로 사용한다면 하위 View에서는 State 대신 Binding을 사용하며,
이 경우엔 Private 키워드를 사용할 수 없고, 기본값도 사용할 수 없다.

'학습 노트 > Swift UI (2022)' 카테고리의 다른 글

25. StateObject  (0) 2022.11.02
24. Observable Object & Environment Object  (0) 2022.11.01
22. NavigationView & TabView  (0) 2022.10.25
21. Animation  (0) 2022.10.07
20. Image & SFSymbol & AsyncImage  (0) 2022.10.06