본문 바로가기

개발/Swift

@StateObject @ObservedObject @EnvironmentObject의 차이와 올바른 사용방법

 

 

항상 이 세가지를 사용하면서 의문이 들었습니다.

@EnvironmentObject는 모든 하위 뷰에서 적용이 가능하다는걸 알았지만, 정확히 무엇과 같이 작동하는지 몰랐습니다.

이번에 공식문서와 다양한 자료들을 수집하면서 알게되어 쉽게 설명해보고자 합니다.

 

 

@StateObject
ObservableObject를 생성하고 관찰하는 객체

@StateObject는 생성하는 PropertyWrapper로, 선언한 뷰와 함께 생성되고 사라집니다. (Life Cycle을 함께함)

 ** 생성한다는 것은 Memory에 올린다는 말이고, 그것을 Apple공식문서에서는 Instance화 한다고 합니다.

따라서 주로, View를 나오면 데이터를 초기화 하고싶을 때 사용합니다.

 

@State와 비슷하지만, @State는 단순한 개체를, @StateObject는 ViewModel과 같은 복잡한 객체를 관찰합니다.

 

 

@ObservedObject
@StateObject에서 생성한 객체를 상속받는데 사용

@ObservedObject는 Instance화 된 객체를 관찰합니다. (Instance화에 관여하지 않습니다.)

따라서 보통의 경우 ObservedObject로 ViewModel을 초기화 하거나 하지 않습니다.

 

예를 들면 ViewModel을 초기화 하고 사용한다면 @StateObject로 초기화하고,

하위 뷰에서 ObeservedObject로 상속받아 사용합니다.

// DataModel 정의
class DataModel: ObservableObject {
    @Published var name = "Heon"
    @Published var isEnabled = false
}

// MyView (예시에서 상위 뷰)
struct MyView: View {
    @StateObject private var dataModel = DataModel() // StateObject를 생성(Instance화)

    var body: some View {
        MySubView(model: dataModel)
            // MySubView에서 
    }
}

// MySubView (MyView의 하위뷰)
struct MySubView: View {
    @ObservedObject var dataModel: DataModel // MyView에서 초기화한 DataModel을 상속받음

    var body: some View {
        Text(model.name) // Heon 출력, @Published 된 데이터가 다른것으로 바뀌면 View를 다시 그림
    }
}

 

@EnvironmentObject

@EnvironmentObject는 하위의 모든 View에서 상속 받을 수 있도록 합니다.

하위 뷰들에서만 상속가능하고, 타입 당 1개의 ObservableObject 당 1개의 EnvironmentObject를 전달할 수 있다는 특징을 가집니다.

// DataModel 정의
class DataModel: ObservableObject {
    @Published var name = "Heon"
    @Published var isEnabled = false
}

// MyView (예시에서 상위 뷰)
struct MyView: View {
    @StateObject private var dataModel = DataModel() // StateObject를 생성(Instance화)

    var body: some View {
        MySubView()
            .environmentObject(dataModel) 
            // MySubView 하위의 모든 View에서 @EnvironmentObject로 상속 가능하도록 함
    }
}

// MySubView (MyView의 하위뷰)
struct MySubView: View {

    var body: some View {
        MySecondSubView()
    }
}

// MySecondSubView (MyView의 하위 뷰)
struct MySecondSubView: View {
    @EnvironmentObject var model: DataModel  // MyView에서 생성한 model을 사용할 수 있음

    var body: some View {
        Text(model.name) // Heon 출력, @Published 된 것이 다른것으로 바뀌면 데이터 변경 됨
    }
}

 

빠른 이해를 위해 간단하게 기재해보았습니다.

이후 공식문서를 읽으신다면 빠르게 이해 되실 것이라 생각됩니다!

 

@StateObject

 

StateObject | Apple Developer Documentation

A property wrapper type that instantiates an observable object.

developer.apple.com

@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

@EnvironmentObject

 

EnvironmentObject | Apple Developer Documentation

A property wrapper type for an observable object supplied by a parent or ancestor view.

developer.apple.com

 

반응형