SwiftUI를 사용하다 보면 ObservableObject를 채택해 모델의 데이터 변경사항을 구독할 때가 있다. 어떤 상황에서 쓰는지 두개의 특성을 비교해 보도록 한다.
뷰가 인스턴스를 생성하면 뷰가 삭제되고 다시 그려질 때마다 생성된다.
이해를 돕기 위해 간단한 코드를 작성하고 살펴보도록 한다.
class DataSource: ObservableObject {
@Published var counter = 0
}
struct Counter: View {
@ObservedObject var dataSource = DataSource()
var body: some View {
VStack {
Button("Increment counter") {
dataSource.counter += 1
}
Text("Count is \(dataSource.counter)")
}
}
}
struct ItemList: View {
@State private var items = ["hello", "world"]
var body: some View {
VStack {
Button("Append item to list") {
items.append("test")
}
List(items, id: \.self) { name in
Text(name)
}
Counter()
}
}
}
배열을 보여주는 리스트가 있고, 배열을 추가시킬 수 있으며 하단에는 카운터를 증가시키는 텍스트를 배치하였다.
여기서 ObservedObject의 특성이 드러나는데
배열추가버튼을 누르면 카운터가 0으로 초기화된다. 초기화 -> 인스턴스가 유지되지 않고 초기화가 되는것. 즉 뷰를 다시그리는 작업을 하게 된다.
그런데 만약 배열에 추가를 하고 증가한 카운터의 숫자도 유지하고 싶다면 StateObject를 사용해야 한다. 인스턴스가 유지되고 재사용 되기 때문이다.
뷰가 삭제되고 다시 그려진 후에도 인스턴스가 유지되고 재사용된다.
StateObject는 ObservedObject와 거의 동일한 방식으로 작동하지만 둘 사이의 가장 큰 차이점은 소유권이다. StateObject 객체를 생성하는 뷰는 데이터 소유자. 따라서 해당 개체의 변경사항을 보고 싶다면 @ObservedObject를 사용하여 확인한다. 다만 확인은 가능하되 소유는 불가능 한 것
이제 둘의 차이점을 알게 되었다. 올바르게 코드를 작성하는 법은 무엇일까?
struct LibraryView: View {
@StateObject private var book = Book()
var body: some View {
BookView(book: book)
}
}
객체를 최초의 뷰(LibraryView)에서 한번 생성하고 값을 넘긴다.
그렇다면 BookView에서는? @ObservedObject로 받으면 되는 것
앱 전체에서 개체를 공유하려고 할 때에도
@main
struct BookReader: App {
@StateObject private var library = Library()
var body: some Scene {
WindowGroup {
LibraryView()
.environmentObject(library)
}
}
}
struct LibraryView: View {
@EnvironmentObject var library: Library
// ...
}
a -> b -> c로 데이터의 흐름이 있다고 가정하자.
a(StateObject) -> b(observedObject) -> c(observedObject)
로 데이터를 받아야 하는 것은 꽤나 불편한 작업일 것이다. 따라서 환경에 배치하여 모든 하위 뷰에서는 속성을 사용해 인스턴스에 접근할 수 있을 것이다.
참고자료
1.https://developer.apple.com/documentation/swiftui/managing-model-data-in-your-app
2.https://stackoverflow.com/questions/62544115/what-is-the-difference-between-observedobject-and-stateobject-in-swiftui
3.https://www.hackingwithswift.com/quick-start/swiftui/whats-the-difference-between-observedobject-state-and-environmentobject
4.https://www.donnywals.com/whats-the-difference-between-stateobject-and-observedobject/