관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - SwiftUI] @StateObject vs @ObservedObject (#ViewModel, 뷰 상태관리) 본문

iOS 응용 (SwiftUI)

[iOS - SwiftUI] @StateObject vs @ObservedObject (#ViewModel, 뷰 상태관리)

jake-kim 2024. 9. 13. 01:41

@StateObject와 @ObservedObject 개념

  • @StateObject와 @ObservedObject 모두 ObservableObject 모델을 옵저빙할 때 사용
class MyViewModel: ObservableObject {
    @Published var count = 0
}

@StateObject var viewModel = MyViewModel()
@ObservedObject var viewModel = MyViewModel()
  • 차이점?
    • @ObservedObject 기능: 뷰가 다시 그려질 때, 뷰 내부에 @ObservedObject 모델을 두면 초기화됨
    • @StateObject 기능: 뷰가 다시 그려질 때, 뷰 내부에 @StateObject 모델을 두어도 데이터가 유지됨

뷰 상태관리 방법

  • 뷰를 사용할 때 뷰에 그릴 데이터를 어디서 관리할 것인가?
    • 뷰 외부 -> @ObservedObject 사용할 것
    • 뷰 내부 -> @StateObject

사용 예시

  • 상위 뷰 에서 데이터 하나로 관리하고, 하위 뷰에서 그 데이터를 그대로 사용하는 경우, 상위 뷰는 데이터가 계속 유지되어야 하므로 @StateObject로 선언하고, 하위 뷰는 @ObservedObject로 사용
struct ParentView: View {
    @StateObject var viewModel = MyViewModel()

    var body: some View {
        ChildView(viewModel: viewModel)
            .onAppear {
                Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in
                    viewModel.count += 1
                }
            }
    }
}

struct ChildView: View {
    @ObservedObject var viewModel: MyViewModel

    var body: some View {
        Text("Count: \(viewModel.count)")
    }
}
  • 주의사항: @ObservablObject를 뷰 내부에서 초기화한 경우
    • 뷰 내부에서 모델을 생성하고, 모델의 값을 특정 값으로 변경했을 때 반영이 안되는 케이스가 생길 수 있음 (모델이 계속 초기화 되므로)
// bad!
struct ChildView: View {
    @StateObject var viewModel = MyViewModel()

    var body: some View {
        Text("Count: \(viewModel.count)")
    }
}

// good!
struct ChildView: View {
    @ObservedObject var viewModel = MyViewModel()

    var body: some View {
        Text("Count: \(viewModel.count)")
    }
}

 

* 읽어보면 좋은 글

- @StateObject, @ObservedObject, @EnvironmentObject 때에 맞게 사용하기

- @StateObject 사용 주의사항 (Accessing StateObject's object without being installed on a View. This will create a new instance each time.)

 

Comments