SwiftUI로 뷰와 로직을 작성하다 보면 데이터 관리에 대한 고민에 부딪히게 된다.
특히 여러 뷰에서 동일한 데이터를 공유하고 업데이트해야 하는 상황에서 State나 Binding만으로는 한계가 있다.
이때 Combine 프레임워크의 핵심 요소인
ObservableObject, ObservedObject, 그리고 Published를 이해하는 것이 중요하다.
State와 Binding은 주로 상위-하위 뷰 간의 명확한 데이터 흐름에 적합하며, 단일 뷰 내부 또는 계층적으로 연결된 뷰에서 사용하기 좋다. 하지만 외부에 선언된 값을 여러 뷰에서 관찰하고 그 값의 변화에 따라 UI를 업데이트해야 하는 상황에서는 이벤트 변화를 관찰하는 ObservableObject와 ObservedObject가 더 적합하다.
1. ObservableObject: 객체의 변화를 알려줄게!
- ObservableObject는 객체 내부의 변경 사항이 발생하기 전에 이를 발행(emit)하는 퍼블리셔(publisher)를 가진 타입이다.
- 변화를 감지할 수 있는 객체를 만들 때 사용한다.
- ObservableObject를 채택한 클래스의 프로퍼티들을 관찰하고 있다가, 이 프로퍼티의 변화가 감지되면 해당 객체를 사용하는 뷰를 다시 그려 업데이트하는 역할을 수행한다.
- "이 객체의 값이 바뀌었으니, 업데이트를 진행시켜!" 하고 알리는 역할을 한다.
2. Published: 나 값 바뀌었다!
- Published는 @Published 어트리뷰트로 표시된 프로퍼티의 변경 사항을 발행하는 타입이다.
- ObservableObject 클래스 내부에 선언될 때, 해당 프로퍼티의 값이 변경되면 자동으로 willSet 역할을 하는 objectWillChange 퍼블리셔를 호출하여 뷰를 업데이트하도록 알린다.
- 주로 ObservableObject와 함께 사용된다.
- "나의 값이 바뀌었으니, 뷰를 업데이트해야 해!" 하고 외부에 알리는 역할을 한다.
ObservableObject와 Published 사용 예시
class UserSettings: ObservableObject {
@Published var username = "Anonymous"
@Published var count = 0
@Published var isOn = false
}
- 공식문서에도 따로 강조되어 있는 부분인데, ObservableObject와 Published는 class 내에서만 사용해야한다.
- 사용자와 관련된 값을 관찰하기 위해 UserSettings라는 ObservableObject 클래스를 선언했다. 그 안에 관찰하고 싶은 값들을 @Published로 선언했다.
- Published로 선언한 username, count, isOn의 값에 변화가 생기는지 시스템이 자동으로 관찰한다.
3. ObservedObject: 바뀐 값을 받아서 뷰 업데이트!
- ObservedObject는 ObservableObject를 따르는 객체를 구독(subscribe)하고, 해당 객체의 상태가 변할 때마다 뷰를 무효화하여 UI를 업데이트하는 프로퍼티 래퍼 타입이다.
- 뷰 외부에서 생성된 객체의 상태 변화를 구독하고, 그 상태가 변했을 때마다 해당 뷰를 업데이트한다.
- "내가 관찰 중이던 값이 바뀌었으니, 이 뷰를 업데이트할게!" 하는 역할을 수행한다.
ObservedObject 사용 예시
struct PracticeObservableObject: View {
@ObservedObject var settings = UserSettings()
var body: some View {
VStack {
// MARK: - Change Name
Text("Hello, \(settings.username)")
Button(action: {
settings.username = "New guy"
}, label: {
Text("Change Username")
.labelStyle(.titleOnly)
})
// MARK: - Change Count
Text("count: \(settings.count)")
Button("Add Count") {
settings.count += 1
}
// MARK: - Change Value
Toggle("On", isOn: $settings.isOn)
.padding(.horizontal, 150)
Button("Make it On") {
settings.isOn.toggle()
}
}
}
}
4. PracticeObservableObject 뷰에서 뷰 외부에서 정의된 settings 객체를 @ObservedObject로 선언하여 구독하고 변화를 관찰한다.
5. 버튼 액션에 따라 settings 객체 내부의 @Published 프로퍼티 값이 변화하면, @ObservedObject를 통해 이 변화를 감지하고 자동으로 뷰를 업데이트한다.
시뮬레이터 결과
References
https://developer.apple.com/documentation/Combine/ObservableObject
ObservableObject | Apple Developer Documentation
A type of object with a publisher that emits before the object has changed.
developer.apple.com
https://developer.apple.com/documentation/swiftui/observedobject
ObservedObject | Apple Developer Documentation
A property wrapper type that subscribes to an observable object and invalidates a view whenever the observable object changes.
developer.apple.com
https://developer.apple.com/documentation/combine/published
Published | Apple Developer Documentation
A type that publishes a property marked with an attribute.
developer.apple.com
SwiftUI Cookbook, Chapter 2: Understanding ObservableObject & ObservedObject
Learn how to use the ObservableObject and ObservedObject property wrappers in SwiftUI for shared state management across multiple views.
www.kodeco.com
'Dev > SwiftUI' 카테고리의 다른 글
[SwiftUI] LifeCycle (1) | 2024.10.14 |
---|---|
[SwiftUI] Navigation (0) | 2024.09.24 |
[SwiftUI] scrollTargetLayout과 ScrollTargetBehavior (0) | 2024.08.16 |
[SwiftUI] Property Wrapper 총정리 (0) | 2024.07.26 |
[SwiftUI] Frame (0) | 2024.07.22 |