J
[SwiftUI] @ObservableObject / @Published / @StateObject / @ObservedObject 본문
SwiftUI
[SwiftUI] @ObservableObject / @Published / @StateObject / @ObservedObject
yujaehui 2024. 5. 20. 12:23`@ObservableObject`, `@Published`, `@StateObject`, `@ObservedObject`는 상태 관리와 데이터 흐름을 위한 속성 래퍼.
이 속성들은 각기 다른 용도로 사용되며, 뷰와 데이터 모델 간의 데이터를 연결하고 상태 변경 시 뷰를 업데이트하는 역할.
1. `@ObservableObject`
정의
- `@ObservableObject`는 관찰 가능한 객체를 정의하는 데 사용.
- `ObservableObject` 프로토콜을 채택한 클래스에 적용하며, 해당 객체에서 발생하는 상태 변경을 뷰에 알림.
주요 특징
- 클래스에 사용
- Swift의 `class`에서만 사용할 수 있음.
- Publisher 역할
- `@Published` 속성이 변경되면 `ObservableObject`는 변경 사실을 알림.
- Combine의 `@Published`와 함께 사용
- `@Published`는 `ObservableObject` 내부에서 속성의 변화를 자동으로 퍼블리시.
예제
class CounterViewModel: ObservableObject {
@Published var count: Int = 0
func increment() {
count += 1
}
}
- `CounterViewModel`은 `ObservableObject`로 선언되었고, `count` 속성은 `@Published`로 선언되어 변화가 자동으로 퍼블리시.
2. `@Published`
정의
- `@Published`는 관찰 가능한 프로퍼티를 정의하는 속성 래퍼.
- `ObservableObject` 내부에서만 사용할 수 있음.
주요 특징
- Publisher 생성
- `@Published`는 Combine의 Publisher로 작동하여 상태 변경을 방출.
- 자동 알림
- 값이 변경되면 `ObservableObject`를 통해 해당 변경 사항이 자동으로 구독자에게 전달.
예제
class TimerViewModel: ObservableObject {
@Published var time: String = "00:00"
func updateTime(to newTime: String) {
time = newTime
}
}
3. `@StateObject`
정의
- 새로운 `ObservableObject`를 소유하는 SwiftUI 뷰에서 사용.
- 뷰의 라이프사이클 동안 해당 객체를 유지.
주요 특징
- 소유권
- `@StateObject`는 SwiftUI 뷰가 객체의 소유권을 가짐.
- 뷰가 다시 생성되더라도 객체는 동일한 인스턴스를 유지.
- 초기화 보장
- SwiftUI 뷰에서 한 번만 초기화.
사용 시기
- 새로 생성한 객체를 SwiftUI 뷰의 상태로 관리하려는 경우.
예제
struct CounterView: View {
@StateObject private var viewModel = CounterViewModel()
var body: some View {
VStack {
Text("Count: \\(viewModel.count)")
Button("Increment") {
viewModel.increment()
}
}
}
}
- `@StateObject`는 뷰가 viewModel의 소유권을 가지며, 상태 변경 시 뷰가 업데이트.
4. `@ObservedObject`
정의
- SwiftUI 뷰가 소유하지 않는 `ObservableObject`를 관찰하는 속성 래퍼.
- 다른 뷰에서 전달받은 객체를 관찰할 때 사용.
주요 특징
- 소유권 없음
- `@ObservedObject`는 객체의 생명주기를 관리하지 않음.
- 전달된 객체의 상태만 관찰.
- 데이터 바인딩
- `@ObservedObject`는 상태 변경을 감지하고 뷰를 업데이트.
사용 시기
- 부모 뷰에서 자식 뷰로 `ObservableObject`를 전달받아 관찰할 때.
예제
struct ParentView: View {
@StateObject private var viewModel = CounterViewModel()
var body: some View {
DetailView(viewModel: viewModel)
}
}
struct DetailView: View {
@ObservedObject var viewModel: CounterViewModel
var body: some View {
VStack {
Text("Detail Count: \\(viewModel.count)")
Button("Increment") {
viewModel.increment()
}
}
}
}
- `ParentView`에서 생성한 `viewModel`을 `DetailView`로 전달하여 관찰하고 상태를 공유.
5. `@StateObject` vs `@ObservedObject`
`@StateObject` | `@ObservedObject` | |
소유권 | 뷰가 객체를 소유하며 상태를 관리 | 객체의 소유권이 없으며 외부에서 전달받아 관찰 |
라이프사이클 | 뷰의 생명주기 동안 유지 | 전달받은 객체의 상태만 관찰 |
초기화 | 한 번만 초기화 | 초기화되지 않으며 전달받아 사용 |
사용 시기 | 뷰가 상태 관리 객체를 처음 생성해야 하는 경우 | 외부에서 전달받은 상태 객체를 관찰해야 하는 경우 |
6. 정리
- `@ObservableObject`: 클래스가 상태 변화를 퍼블리시할 수 있도록 정의.
- `@Published`: `ObservableObject` 내부에서 상태 변경을 퍼블리시.
- `@StateObject`: 뷰가 `ObservableObject`를 소유하고 상태를 관리.
- `@ObservedObject`: 외부에서 전달받은 `ObservableObject`를 관찰.
'SwiftUI' 카테고리의 다른 글
[SwiftUI] SwiftUI + TCA : Redux 패턴 영향? 단방향? (0) | 2024.06.30 |
---|---|
[SwiftUI] @AppStorage (0) | 2024.05.23 |
[SwiftUI] @ViewBuilder (0) | 2024.05.20 |
[SwiftUI] AsyncImage in SwiftUI (0) | 2024.05.13 |
[SwiftUI] ForEach in SwiftUI (0) | 2024.05.13 |