apple/SwiftUI & Combine

[SwiftUI] @StateObject

lgvv 2022. 6. 2. 20:56

@StateObject

 

✅ 아래 공식문서를 바탕으로 작성하였습니다.

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

 

Apple Developer Documentation

 

developer.apple.com

 

관찰가능한 객체를 인스턴스화 하는 프로퍼티 래퍼 타입입니다.

특성 선언에 @StateObject 속성을 적용하고 ObservableObject 프로토콜을 준수하는 초기 값을 제공하여 View, App 또는 Scene에서 상태 개체를 만듭니다.

@StateObject var model = DataModel()

 

SwiftUI에서는 객체를 선언하는 인스턴스에 대해 한 번만 객체의 새 인스턴스를 생성합니다. 관찰 가능한 객체의 속성이 변경되면 SwiftUI는 해당 속성에 의존하는 뷰의 일부를 업데이트합니다.

Text(model.title) // Updates the view any time `title` changes.

우리는 ObservedObject 속성을 이용해서 있는 속성에 state 객체를 전달할 수 있습니다.

다른 방법으로는 environmentObject(_:) modifier를 적용함으로서 뷰의 계층에 환경에 적용할 수 있습니다. 

ContentView()
    .environmentObject(model)

위의 코드에서 보다시피 만약 environment object를 생성하게 되면 ContentView 안에 있는 객체 또는 그것의 하위 계층에 어디서든 EnvironmentObject 속성을 읽을 수 있습니다.

 

여기서 잠깐! State와 Binding을 이용한 기법과 environmentObject를 사용하는 것과의 차이를 알아봅시다.

 

State와 Binding은 주로 1:1 상황에서 유용하다

다만, 하나의 변수가 여러 하위 계층을 건너가야 하는 경우 State와 Binding으로 만들어두면 너무 불편하다.

이 경우에 사용하는 것이 environment이다.

Kuring 프로젝트에서 UIKit을 SwiftUI로 변경할 때 HomeView - NoticeWebView - WebView 이렇게 세가지에서 NoticeModel이 공유되었는데, 이런 경우에 사용하면 BEST!

 

이 사진 한장으로 싹 정리!

 

@EnvironmentObject var model: DataModel

$ 연산자를 사용하여 상태 개체의 속성 중 하나에 대한 @Binding을 가져옵니다. 개체의 속성 중 하나에 대한 양방향 연결을 만들려면 바인딩을 사용하십시오. 예를 들어, 모델에 저장된 isEnabled라는 부울 값을 Toggle이 제어하도록 할 수 있습니다.

Binding에서 상태에 대한 데이터 값을 사용하려면 쉽게 말해서 $ 연산자를 사용해라!! 

RxSwift 생각하면 상태를 관찰하려고 구독한다는 느낌!

Toggle("Enabled", isOn: $model.isEnabled)