EnvironmentObject, ObservedObject, StateObject 세가지의 특징을 간단한 예제를 통해 알아보자
class ViewModel: ObservableObject {
@Published var count = 0
}
@main
struct [YourAppName]: App {
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(ViewModel())
}
}
}
struct ContentView: View {
@EnvironmentObject var environment: ViewModel
var body: some View {
VStack {
AView(observed: ViewModel())
Button("\(environment.count)") {
environment.count += 1
}
}
}
}
struct AView: View {
@ObservedObject var observed: ViewModel
var body: some View {
VStack {
BView(state: ViewModel())
Button("\(observed.count)") {
observed.count += 1
}
}
.frame(width: 300, height: 300, alignment: .top)
.background(Color.yellow)
}
}
struct BView: View {
@StateObject var state: ViewModel
var body: some View {
VStack {
CView()
Button("\(state.count)") {
state.count += 1
}
}
.frame(width: 200, height: 200, alignment: .top)
.background(Color.green)
}
}
struct CView: View {
@EnvironmentObject var environment: ViewModel
var body: some View {
VStack {
Button("\(environment.count)") {
environment.count += 1
}
}
.frame(width: 100, height: 100)
.background(Color.orange)
}
}
간단하게 버튼을 누르면 1씩 증가하는 예제인데 하나의 ObservableObject를 채택한 ViewModel을 @EnvironmentObject, @ObservedObject, @StateObject를 사용해 비교해보자.
@EnvironmentObject
먼저 가장 바깥의 버튼과 가장 안쪽의 버튼은 하나의 @EnvironmentObject를 바라보고 있으므로 어떤 것을 클릭해도 두 개의 값이 동시에 변하는 것을 볼 수 있다.
가장 부모 뷰에 .environmentObject(ViewModel())함수를 통해 주입을 해주면 하위 뷰 어느 곳에서나 따로 전달을 하지 않아도 사용할 수 있다.
@ObservedObject
노란색 뷰의 버튼은 @ObservedObject를 사용했는데 부모 뷰가 다시 렌더링 될 때마다 @ObservedObject도 다시 주입을 하여 count값이 초기 값으로 바뀌는 것을 볼 수 있다.
+) 만약 부모 뷰가 리 렌더링 되지 않는다면 @ObservedObject의 값도 초기화가 안될까??
기존에는 주황색 뷰의 버튼을 클릭하면 @EnvironmentObject 값이 변경 > ContentView의 값이 변경 되면서 리 렌더링 > 자식 뷰의 뷰모델을 다시 주입하여 값이 초기화가 되었지만,
ContentView의 @EnvironmentObject코드를 모두 주석 처리하고 다시 빌드하여 테스트했을 때 주황색 뷰의 버튼을 클릭해도 부모 뷰를 다시 그리지 않아 @ObservedObject값도 초기화가 안되었다.
@StateObject
@ObservedObject의 단점을 보완하기 위해 SwiftUI2에서 추가된 @StateObject이다. 초록색 뷰의 버튼은 @StateObject를 사용하였는데 부모 뷰가 렌더링 되어도 기존 값을 그대로 유지하고 있다.
'iOS > SwiftUI' 카테고리의 다른 글
SwiftUI와 상태관리 (0) | 2022.04.03 |
---|---|
SwiftUI에서 스켈레톤 UI 적용하기 (0) | 2022.02.20 |
[Swift] Codable로 JSON파싱하기 -확장- (0) | 2022.01.30 |
[Swift] Codable로 JSON파싱하기 -기초- (0) | 2022.01.30 |
[SwiftUI] PencilKit을 사용해 캔버스 만들기 (0) | 2022.01.15 |