Category/iOS

ObservableObject와 @StateObject, @ObservedObject란?

Corinee 2024. 9. 21. 18:46
728x90

SwiftUI에서 상태 관리데이터 공유를 위해 사용하는 주요 도구들 중 하나가 ObservableObject와 그 관련 속성 래퍼들인 @StateObject, @ObservedObject 입니다. 이들은 여러 뷰 간에 상태를 관찰하고 변경을 자동으로 반영할 수 있도록 도와줍니다.

1. ObservableObject

ObservableObject는 SwiftUI에서 상태를 관리하고 뷰 간에 공유하기 위해 사용하는 클래스입니다. @State와 같은 단순한 값이 아닌, 더 복잡한 데이터와 로직을 관리할 때 주로 사용됩니다.

특징:

  • 클래스 기반: ObservableObject는 클래스에서만 사용할 수 있습니다.
  • 객체가 변경될 때 알림: ObservableObject는 객체의 상태가 변경될 때 SwiftUI에 그 변화를 알릴 수 있습니다. 이를 통해 SwiftUI는 해당 객체를 사용하는 뷰를 다시 렌더링합니다.
  • @Published 속성: ObservableObject에 있는 속성은 @Published로 선언해야, 상태가 변경될 때 자동으로 알림이 발생합니다.

예시:

class CounterModel: ObservableObject {
    @Published var count: Int = 0
}

이 클래스는 count라는 상태를 가지고 있으며, 이 상태가 변경될 때 이를 자동으로 알림으로 보내, 관련된 모든 뷰가 다시 그려지도록 합니다.

2. @StateObject

@StateObject는 SwiftUI에서 객체의 상태를 관리하기 위한 속성 래퍼입니다. 뷰가 처음 생성될 때 객체를 초기화하고, 그 이후로는 해당 객체의 상태를 지속적으로 관리합니다. @StateObject는 해당 뷰가 객체의 소유자임을 나타내며, 새로 객체를 생성하고 라이프사이클을 관리합니다.

특징:

  • 뷰가 처음 생성될 때만 객체를 초기화합니다.
  • 객체가 뷰의 라이프사이클에 따라 재사용됩니다. 즉, 뷰가 다시 그려질 때(View body가 재실행될 때) @StateObject는 다시 생성되지 않습니다.
  • @StateObject는 객체를 소유하고, 객체의 상태를 유지하며, 객체가 변경될 때마다 뷰를 다시 렌더링합니다.

예시:

struct ContentView: View {
    @StateObject var counterModel = CounterModel() // CounterModel의 소유자

    var body: some View {
        VStack {
            Text("Count: \(counterModel.count)")
            Button("Increase Count") {
                counterModel.count += 1
            }
        }
    }
}

여기서 ContentView는 counterModel 객체의 소유자이며, @StateObject를 통해 상태를 관리합니다. 버튼을 클릭할 때마다 count가 증가하고, SwiftUI는 자동으로 상태 변화에 따라 UI를 다시 렌더링합니다.

3. @ObservedObject

@ObservedObject는 SwiftUI에서 외부에서 전달받은 객체의 상태를 관찰하는 속성 래퍼입니다. @StateObject와 달리, @ObservedObject는 객체를 생성하거나 소유하지 않습니다. 대신, 다른 곳에서 전달된 객체의 상태를 관찰만 합니다.

특징:

  • 뷰가 객체의 소유자가 아님: 객체는 다른 뷰에서 전달된 것이며, 상태를 관찰만 하고 생성하지 않습니다.
  • 객체의 상태가 변경되면, @ObservedObject를 사용하는 뷰가 자동으로 다시 렌더링됩니다.
  • 주로 상위 뷰에서 객체를 생성하고, 하위 뷰에서 그 객체를 관찰할 때 사용합니다.

예시:

struct ChildView: View {
    @ObservedObject var counterModel: CounterModel // 외부에서 전달된 상태를 관찰

    var body: some View {
        VStack {
            Text("Child Count: \(counterModel.count)")
        }
    }
}

struct ParentView: View {
    @StateObject var counterModel = CounterModel() // 객체를 생성하고 소유

    var body: some View {
        VStack {
            ChildView(counterModel: counterModel) // @ObservedObject로 전달
            Button("Increase Count") {
                counterModel.count += 1
            }
        }
    }
}
  • ParentView는 @StateObject를 사용해 counterModel을 생성하고 관리합니다.
  • ChildView는 @ObservedObject를 통해 ParentView에서 전달받은 객체관찰합니다.
  • 상태가 변경되면 ParentView와 ChildView는 자동으로 UI를 업데이트합니다.

차이점 요약

속성 래퍼소유권상태 변경 시 뷰 업데이트객체 생성 여부사용 용도

@State 소유 값 타입 (Int, String 등) 단순 값 타입 상태 관리
@StateObject 소유 뷰가 직접 객체를 생성 뷰가 객체를 소유하고 관리할 때
@ObservedObject 비소유 다른 뷰에서 전달받은 객체를 관찰 상위 뷰로부터 객체를 전달받아 상태를 관찰할 때

요약

  • ObservableObject는 여러 뷰 간에 상태를 공유할 때 사용하는 클래스 기반 상태 관리 도구입니다. 상태가 변경될 때 자동으로 뷰가 업데이트됩니다.
  • @StateObject는 뷰가 객체를 생성하고 소유하며, 뷰가 해당 객체의 상태를 지속적으로 관리합니다. 객체를 처음 생성할 때 사용합니다.
  • @ObservedObject는 뷰가 객체를 소유하지 않고 관찰만 하며, 상태가 변경될 때 해당 뷰가 자동으로 업데이트됩니다. 이미 생성된 객체를 전달받아 관찰할 때 사용합니다.

이렇게 @StateObject, @ObservedObject, 그리고 ObservableObject를 적절히 활용하면, SwiftUI에서 뷰 간 상태 관리를 효율적으로 할 수 있습니다.

728x90