SwiftUI의 @EnvironmentObject - 2

June·2023년 2월 20일
0

SwiftUI-Data

목록 보기
7/12
post-thumbnail

부모 뷰와 자식 뷰 관계에서 액세스 가능한 범위

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를 별도로 세팅해주지 않는 이상) 해당 데이터에 액세스가 불가능하다.

  • 어떤 부모 뷰가 environmentObject를 이용해 어떤 데이터에 액세스할 수 있게 설정되었다면, 그 부모 뷰의 자식 뷰에서도 그 데이터에 액세스 가능.

가장 하위의 뷰(리프 노드)에서 @EnvironmentObject에 접근하기


이미지의 10번 노드가 .environmentObject 수정자를 통해 ObservableObject객체를 전달받은 상태라고 가정할 때(쉽게 말해 10번이 부모 뷰), 14번, 13번 노드는 모두 10번 노드의 자식 뷰들이다.
이 때, 13번 뷰에서만 ObservableObject 데이터에 액세스하려고 한다면?

13번 뷰를 위해 14번 뷰에서도 해당 데이터에 액세스해야 하는 걸까?

그렇지 않다.
가장 하위의 뷰에서 해당 데이터에 액세스한다고 해서, 모든 하위 뷰에서 해당 데이터에 접근할 필요는 없다.

즉, 13번 뷰에서만 해당 데이터에 접근이 필요하면, 14번 뷰를 거칠 필요 없이 13번 뷰에서만 데이터 접근이 가능하다는 의미이다.


init()에서 사용 불가

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 {
		// ...
    }
}
  • init에서 EnvironmentObject에 접근 불가.


정리

@EnvironmentObject는 언제 사용하나?

  • 뷰에서 특정 데이터에 전역적으로 접근하고자 할 때
  • 데이터와 UI간 양방향 바인딩을 생성하려고 할 때
  • 1개의 ObservableObject가 업데이트 되면 여러개의 뷰가 동시에 업데이트되기를 원할 때
  • @EnvironmentObject는 ObservableObject를 준수한 class와 함께 사용 가능
profile
안다고 착각하지 말기

0개의 댓글