class Animal: ObservableObject {
@Published var animal: String = "랙돌, 먼치킨, 러시안블루"
}
struct ThisIsEnvironmentObject: View {
var body: some View {
TabView {
TabOne()
.tabItem {
Image(systemName: "1.circle")
Text("One")
}
TabTwo()
.tabItem {
Image(systemName: "2.circle")
Text("Two")
}
.environmentObject(Animal()) // TabTwo에만 세팅해줌
}
.font(.title)
}
}
struct TabOne: View {
var body: some View {
VStack {
Text("탭 1")
.font(.largeTitle)
Text("EnvironmentObject란??")
.font(.title)
.padding()
Spacer()
}
}
}
struct TabTwo: View {
var body: some View {
NavigationView {
VStack {
Text("탭 2")
.font(.largeTitle)
Text("아래 텍스트를 눌러 하위 뷰로 이동")
.font(.headline)
.padding()
Spacer()
NavigationLink {
TabTwoChild()
} label: {
Text("하위 뷰로 이동하기")
}
Spacer()
}
}
}
}
struct TabTwoChild: View {
@EnvironmentObject var animal: Animal
var body: some View {
VStack {
Label {
Text("현재 뷰의 부모 뷰인 TabTwo에서 environmentObject로 ObservableObject(Animal) 객체를 전달했기 때문에, 현재 뷰에서도 해당 데이터에 접근이 가능.\n아래 텍스트를 수정해보자.")
.font(.headline)
} icon: {
Image(systemName: "exclamationmark.circle")
.foregroundColor(.red)
}
Spacer()
TextEditor(text: $animal.animal)
.border(Color.orange, width: 3)
.frame(height: 150)
}
.navigationTitle("TabTwoChild")
}
}
위 코드를 보면 ThisIsEnvironmentObject에서 TabTwo에만 .environmentObject를 세팅해줬다.
따라서 TabTwo의 하위 뷰인 TabTwoChild에서도 해당 데이터에 액세스가 가능한 것을 볼 수 있다.
하지만, TabTwo와 별개인 TabOne에서는(TabOne에 environmentObject를 별도로 세팅해주지 않는 이상) 해당 데이터에 액세스가 불가능하다.
이미지의 10번 노드가 .environmentObject 수정자를 통해 ObservableObject객체를 전달받은 상태라고 가정할 때(쉽게 말해 10번이 부모 뷰), 14번, 13번 노드는 모두 10번 노드의 자식 뷰들이다.
이 때, 13번 뷰에서만 ObservableObject 데이터에 액세스하려고 한다면?
그렇지 않다.
가장 하위의 뷰에서 해당 데이터에 액세스한다고 해서, 모든 하위 뷰에서 해당 데이터에 접근할 필요는 없다.
즉, 13번 뷰에서만 해당 데이터에 접근이 필요하면, 14번 뷰를 거칠 필요 없이 13번 뷰에서만 데이터 접근이 가능하다는 의미이다.
import SwiftUI
class UserViewModel: ObservableObject {
@Published var name = "June"
}
struct ThisIsEnvironmentObject: View {
@EnvironmentObject var viewModel: UserViewModel
@State private var isToggled = false
// init에서 EnvironmentObject에 접근 시도시 에러 발생
init() {
if viewModel.name == "June" {
isToggled = true
}
}
var body: some View {
// ...
}
}