@StateObject 와 @ObservableObject 를 또 검색해보다가 이번에 그냥 직접 이것저것 해보면 기억에 남지 않을까 싶어서 실험해봤다. 궁금했던 건 RootView 아래에 ContentView 가 있고, ContentView 에서 각각 NavigationLink 와 sheet으로 NavigationLinkView 와 sheetView 에 연결된다고 할 때, source of truth 가 어디까지 자동으로 상속되는가!
그러니까 대충 이런 구조
struct Root: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: NavigationLinkView()) {
Text("contentView")
}
}
.sheet(isPresented: $isPresented) {
SheetView()
}
}
}
}
1. Root 에서 environmentObject 로 넘기는 경우
struct Root: App {
@StateObject var fromRoot = someClass()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(fromRoot)
}
}
}
struct ContentView: View {
@EnvironmentObject var fromRoot: someClass
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: NavigationLinkView()) {
Text("contentView")
}
}
.sheet(isPresented: $isPresented) {
SheetView()
}
}
}
}
struct NavigationLinkView: View {
@EnvironmentObject var fromRootOrContentView: someClass
}
struct SheetView: View {
@EnvironmentObject var fromRootOrContentView: someClass
}
| ContentView | NavigationLinkView | SheetView |
---|
상속 | O | O | O |
2. Root 에서 ObservedObject로 Contentview 에만 넘겨주는 경우
struct Root: App {
@StateObject var fromRoot = someClass()
var body: some Scene {
WindowGroup {
ContentView(fromRoot: fromRoot)
}
}
}
struct ContentView: View {
@ObservedObject var fromRoot: someClass
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: NavigationLinkView()) {
Text("contentView")
}
}
.sheet(isPresented: $isPresented) {
SheetView()
}
}
}
}
struct NavigationLinkView: View {
@EnvironmentObject var fromRootOrContentView: someClass
}
struct SheetView: View {
@EnvironmentObject var fromRootOrContentView: someClass
}
| ContentView | NavigationLinkView | SheetView |
---|
상속 | O | X | X |
- ContentView 에서 @StateObject 를 선언하는 경우
struct ContentView: View {
@StateObject var fromContentView: someClass
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: NavigationLinkView()) {
Text("contentView")
}
}
.sheet(isPresented: $isPresented) {
SheetView()
}
}
}
}
struct NavigationLinkView: View {
@EnvironmentObject var fromRootOrContentView: someClass
}
struct SheetView: View {
@EnvironmentObject var fromRootOrContentView: someClass
}
| ContentView | NavigationLinkView | SheetView |
---|
상속 | O | X | X |
4. 2,3번 상황에서 ContentView 의 VStack 에서 .environmentObject() 로 넘겨주는 경우
struct ContentView: View {
@StateObject var fromContentView: someClass
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: NavigationLinkView()) {
Text("contentView")
}
}
.sheet(isPresented: isPresented) {
SheetView()
}
.enviromentObject(fromContentView)
}
}
}
struct NavigationLinkView: View {
@EnvironmentObject var fromRootOrContentView: someClass
}
struct SheetView: View {
@EnvironmentObject var fromRootOrContentView: someClass
}
| ContentView | NavigationLinkView | SheetView |
---|
상속 | O | X | O |
# 5. 2,3번 상황에서 ContentView 의 NavigationView 에서 .environmentObject() 로 넘겨주는 경우
struct ContentView: View {
@StateObject var fromContentView: someClass
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: NavigationLinkView()) {
Text("contentView")
}
}
.sheet(isPresented: isPresented) {
SheetView()
}
}
.enviromentObject(fromContentView)
}
}
struct NavigationLinkView: View {
@EnvironmentObject var fromRootOrContentView: someClass
}
struct SheetView: View {
@EnvironmentObject var fromRootOrContentView: someClass
}
| ContentView | NavigationLinkView | SheetView |
---|
상속 | O | O | O |
# 결론
- sheet, NavigationLink 등으로 연결되는 새로운 view 는 상위 view(e.g. RootView) 의 EnviromentObject 는 상속받으나, 연결이 시작된 view(e.g. ContentView) 의 EnvironmentObject 는 자동으로 상속받지 않는다.
- NavigationLink 로 연결된 view 는 NavigationView 에 EnvironmentObject 주입해야 상속받을 수 있다