@StateObject 데이터를 @ObservedObject를 사용해 자식 뷰와 공유한다.
@ObservedObject없이 데이터의 스냅샷은 얻을 수 있지만, 데이터는 더 이상 업데이트되지는 않는다.
즉 @ObservedObject가 없다면 더 이상 객체의 변경사항을 관찰하지 않는다.
import SwiftUI
/// Weather - 모델
struct Weather: Identifiable {
let id = UUID()
var day = ""
var icon = ""
}
/// Forecast - 뷰모델
class Forecast: ObservableObject {
@Published var forecast = [Weather]()
init() {
forecast = [
Weather(day: "일요일", icon: "cloud.snow.fill"),
Weather(day: "월요일", icon: "sun.min.fill"),
Weather(day: "화요일", icon: "sun.max.fill"),
Weather(day: "수요일", icon: "cloud.sun.fill"),
Weather(day: "목요일", icon: "sun.min.fill"),
Weather(day: "금요일", icon: "cloud.drizzle.fill"),
Weather(day: "토요일", icon: "cloud.sleet.fill")
]
}
func fetchAnotherWeek() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [self] in
forecast.append(contentsOf: forecast)
}
}
}
/// AboutObservedObject - 뷰
struct AboutObservedObject: View {
@StateObject private var weather = Forecast()
@State private var showForecast = false
var body: some View {
NavigationView {
ZStack {
VStack(spacing: 20) {
CommonTextView(title: "", desc: "@ObservedObject 타입의 자식뷰에 @StateObject 레퍼런스 전달")
Text(weather.forecast[0].day)
Image(systemName: weather.forecast[0].icon)
.font(.system(size: 130))
.foregroundColor(.yellow)
Button("2주(14일) 날씨 조회하기") {
showForecast = true
weather.fetchAnotherWeek()
}
}
if showForecast {
ForecastView(weather: weather, showForecast: $showForecast)
}
}
}
}
}
/// ForecastView - 서브뷰
struct ForecastView: View {
@ObservedObject var weather: Forecast
@Binding var showForecast: Bool
var body: some View {
VStack {
List(weather.forecast) { day in
Label {
Text(day.day)
.font(.title)
} icon: {
Image(systemName: day.icon)
.font(.title)
.foregroundColor((.yellow))
}
}
Button("닫기") {
showForecast.toggle()
}
}
}
}
위 코드를 실행하면 AboutObservedObject뷰가 가장 먼저 보여진다.
거기서 '2주(14일) 날씨 조회하기' 버튼을 눌러보면 ForecastView로 이동하며 가장 먼저 일주일치 날씨 데이터가 보여진다. 그리고 1초 후 또 일주일치 날씨 데이터가 추가로 뜨는 것을 볼 수 있다.
ForecastView에 @ObservedObject가 없으면 ForecastView 서브뷰는 더 이상 부모의 @StateObject에 대한 변경 사항을 관찰하지 않는다는 것.
즉 @ObservedObject가 없으면 처음 일주일치 데이터만 출력되고, 1초 후에 추가로 뜨는 다음 일주일치 데이터는 출력되지 않는다는 것이다.
이렇게 @ObservedObject는 데이터의 변경 사항을 해당 뷰에 알리는 역할을 한다.
struct AboutObservedObject_Previews: PreviewProvider {
@StateObject private static var weather = Forecast()
static var previews: some View {
Group {
AboutObservedObject()
ForecastView(weather: weather, showForecast: Binding.constant(true))
// ForecastView(weather: Forecast(), showForecast: .constant(true))
}
}
}
- 프리뷰에서 @State변수를 생성할 수 있지만, previews의 속성이 static이기 때문에 @State변수 역시도 static이어야 한다.
- Binding.constant를 사용해 프리뷰에서 사용하고자 하는 샘플 데이터 전달이 가능하다.