SwiftUI - State, Binding, EnvironmentObject, Published

영점·2022년 11월 4일

간략하게 정의만 작성 ( 추후 예제도 추가 예정 )
직접 사용해보면서 알게 된 점도 적어둘 예정입니다.

@State

@State는 상태를 나타내며, 이 상태가 변경되면 연결된 뷰를 다시 그린다.
따라서 변경된 값을 화면에 보여주어야 할 때 사용하며, 제일 많이 사용된다.

공식 사이트에도 잘 설명되어 있다.

https://developer.apple.com/documentation/swiftui/state/

@State는 이렇게 작성하면 된다. private는 상황에 맞게.. 필수는 아니다!
예시로 간단하게 버튼을 탭했을 때 count가 올라가는 코드를 작성하면..
이렇게 작성할 수 있다.

struct ContentView: View {
    @State private var clickEvent = 1
    
    var body: some View {
        HStack {
            Button(action: {
                clickEvent += 1
            }, label: {
                Text("-")
            })
            .foregroundColor(.gray)
            .frame(width: 30, height: 20, alignment: .center)
            .overlay(
                RoundedRectangle(cornerRadius: 0)
                    .stroke(.gray, lineWidth: 1)
            )
            
            Text(clickEvent.description)
             .foregroundColor(.black)
             .frame(width: 50, height: 30, alignment: .center)
             .overlay(
                 RoundedRectangle(cornerRadius: 0)
                     .stroke(.black, lineWidth: 1)
             )
             .padding()          
         }.padding(.trailing, 20)
    }
}

버튼을 누를때마다 1을 추가하고 해당 값을 텍스트로 출력하는 간단한 예제이다.
( 바인딩해서 하는 예제는 추후 바인딩 작성할 때 추가하도록 하겠습니다 )

..만약 @State를 제외하면.. 뷰 내부에서 demodata의 값을 변경하는 코드가 있다면 Cannot use mutating member on immutable value: 'self' is immutable 에러가 나게 될 것이다.

SwiftUI의 경우 뷰가 구조체로 이루어져있는데, 구조체의 경우 메소드 안의 값을 수정할 수 없기 때문에 값을 변경하게 된다면 에러가 나게된다.
때문에 @State를 이용하여 상태(값)이/가 변경되면 연결된 뷰를 다시 그리는 작업을 한다.
그럼 값을 수정할 수 있다. 위 예제처럼 말이다.

@Binding

@Binding은 상위뷰의 @State를 하위뷰에 공유해야 할 때 하위뷰에서 사용한다.
사용할 때 $ 키워드를 사용한다.

전달"받을거면" @Binding, 전달"해줄거면" @State

EnvironmentObject

@EnvironmentObject는 하위뷰에 모두 공유해야 할 때 사용한다.
공식문서에 따르면 하위뷰에 ObservableObject을 제공한다고..하는데 잘 모르겠다.

검색해보니 사용자 인터페이스 밖에 있으며 앱 내의 SwiftUI 뷰 구조체의 하위 뷰에만 필요한 데이터는 Observable 오브젝트를 이용하고, 사용자 인터페이스 밖에 있으며 여러 뷰에서 접근해야 하는 데이터는 Environment 오브젝트를 활용한다고한다.

음.. 상위뷰에 데이터가 여러개면 Binding이 아니고 Environment를 사용한다는 걸까?
( 해당 부분은 더 공부하고 추가하겠습니다 )

Published

@propertyWrapper struct Published<Value>

@ObservableObject 프로토콜을 준수하는 것은 SwiftUI의 뷰들이 변경사항에 대해 관찰할 수 있다는 의미이다.

class Box: ObservableObject {
    var item = [String]()
}

하지만 유일한 프로퍼티가 @Published로 표시되지 않았기 때문에, 변경사항 알림이 전송되지 않을 것이다. 해서 이 클래스는 배열에 항목들을 자유롭게 추가할 수 있지만 뷰들은 업데이트 하지않고있다.

item에 무언가 추가되거나 제거될때마다 변경사항 알림을 보내고자하는 경우, 다음과 같이 @Published로 표시한다.

class Box: ObservableObject {
    @Published var item = [String]()
}

@Published property wrapper는 실제로 items에 willSet property observer를 추가하므로, 모든 변경사항은 자동으로 관찰자(observers)에게 전송된다.

profile
일단 배운내용은 적어두기

0개의 댓글