Swift - ObservedObject와 StateObject의 차이

  SwiftUI에서 프로퍼티로 @ObservedObject@StateObject라는 것이 존재한다. 각각의 설명을 공식문서로 살펴보면 다음과 같다.



  설명이 조금 다르지만 결국 두 프로퍼티 래퍼는 특정 객체를 관찰하여 값이 변경될 때 View에 해당 변경 사실을 알려주어 뷰를 다시 로드할 수 있도록 하는 기능을 한다.

  이를 실제로 코드에서 어떻게 동작이 다른지 확인해보면

class ObjectViewModel: ObservableObject {
    @Published var number = 0

    func upNumber() {
        number += 1
    }
}

  기본적으로 classObservableObject 프로토콜을 채택시키고 Published를 통해 number가 변화할 경우 해당 값을 참조하는 View들에게 알려줄 수 있다.

struct ContentView: View {
    @State var randomNumber = (0..<1000).randomElement()!
    
    var body: some View {
        VStack {
            Spacer()
            Text("랜덤 숫자 : \(randomNumber)")
            Button("Randomize number") {
                randomNumber = (0..<1000).randomElement()!
            }
        }
        TabView {
            ObservedObjectView()
                .tabItem {
                    Text("ObservedObject View")
                }
            StateObjectView()
                .tabItem {
                    Text("StateObject View")
                }
        }
    }
}

struct ObservedObjectView: View {
    @ObservedObject var observedObjectViewModel = ObjectViewModel()
    
    var body: some View {
        VStack {
            Text("ObservedObject")
            Text("ObjectViewModel의 숫자 값 : \(observedObjectViewModel.number)")
            Button("ObjectViewModel Number값 증가") {
                observedObjectViewModel.upNumber()
            }
        }
    }
}

struct StateObjectView: View {
    @StateObject var stateObjectViewModel = ObjectViewModel()
    
    var body: some View {
        VStack {
            Text("StateObject")
            Text("ObjectViewModel의 숫자 값 : \(stateObjectViewModel.number)")
            Button("ObjectViewModel Number값 증가") {
                stateObjectViewModel.upNumber()
            }
        }
    }
}

  ObservedObjectStateObject의 차이를 확인하기 위해 부모뷰로 ContentView를 만들어주고 해당 뷰 안에 ObservedObjectViewStateObjectView를 넣어 줬다.   기본적으로 두 뷰 모두 ObservedObjectStateObject로 관찰하고 있는 number의 값이 변할 경우 뷰를 다시 그리면서 뷰를 로드한다.   그러나 부모뷰에서 값이 변하면서 뷰가 다시 그려질 경우 ObservedObject의 경우 기존의 값을 읽지 못하고 StateObject의 경우만 기존의 값을 그대로 읽어 뷰를 그리는 모습을 볼 수 있다. 이는 부모뷰가 새로 그려지면서 ObservedObject의 경우는 하위뷰도 새로 그려지면서 뷰모델을 새로 읽어오는 것이기 때문이다.

ObservedObject
StateObject


[참고] https://developer.apple.com/documentation/swiftui/stateobject https://developer.apple.com/documentation/swiftui/observedobject