👉🏻 스위프트에서 @ObservedObject와 @StateObject에 대한 설명입니다.
Here’s an explanation of @ObservedObject and @StateObject in Swift.
👉🏻 @ObservedObject
✔️ @ObservedObject는 구조체의 초기화 시점에 계속해서 인스턴스(프로퍼니 초기화)를 다시 실행 합니다.
@ObservedObject continually re-executes the instance (property initialization) at the time of struct initialization.
✔️ @ObservedObject는 부모뷰에서 전달받은 뷰 모델을 관찰만 합니다.
(관찰이란 뷰모델[Class UserSettings] 값이 변하면 [@Published로 선언된 변수의 값])UI를 업데이트 하는것을 의미합니다.)
@ObservedObject only observes the view model passed from the parent view. (Observation means that when the value of the view model [class UserSettings] changes, the UI is updated [the value of the variable declared with @Published].)
👉🏻 @StateObject
✔️@StateObject는 SwiftUI의 state storage(뷰의 라이프 싸이클 동안 보관되는 저장소)에
인스턴스를 저장하고, 처음 뷰가 생성될 때만 초기화하도록 보장합니다.
@StateObject stores an instance in SwiftUI’s state storage (which is kept throughout the view’s lifecycle) and ensures that it is initialized only when the view is first created.
✔️ @StateObject는 뷰모델의 인스턴스를 생성하고 관리하며 부모뷰에서 사용합니다.
@StateObject creates and manages an instance of the view model and uses it in the parent view.
👉🏻 아래의 코드를 실행해보면 차이를 확인 할 수 있습니다.
You can see the difference by running the code below.
👉🏻@StateObject를 사용할 위치에 @ObservedObject를 사용하면 init()이 두번 실행되는 문제가 발생합니다.
If you use @ObservedObject where you would use @StateObject, you will run into the problem that init() is executed twice.
👉그래서 @StateObject를 사용하면 이런 문제를 방지 할 수 있습니다.
So using @StateObject can help us avoid this problem.
👉🏻코드/code
✔️ ContentView.swift
import SwiftUI
import Combine // add Combine
class MyViewModel: ObservableObject {
@Published var data = ""
init() {
print("MyViewModel init")
fetchData() // 네트워크 호출 같은 작업
}
func fetchData() {
print("fetchData called")
data = "Data Updated..."
}
}
struct ContentView: View {
@State private var count = 0
@ObservedObject var vm = MyViewModel() // 오류 / error
//@StateObject var vm = MyViewModel() // 정상 / normal
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Data:\(vm.data)")
Button("Update view") {
count += 1
print(count)
vm.fetchData()
}
Button("Update Clear") {
count = 0
vm.data = "Clear"
print(count)
}
}
.padding()
}
}
#Preview {
ContentView()
}
✔️ RootView.swift
import SwiftUI
struct RootView: View {
var body: some View {
NavigationStack {
VStack(spacing: 20) {
NavigationLink("Go to ContentView again") {
ContentView() // 뷰 재생성 / Regenerate view
}
ContentView()
.padding()
}
.navigationTitle("RootView")
}
}
}
#Preview {
RootView()
}
👉🏻 스크린 샷 / ScreenShot