EnvironmentValue란
SwiftUI 에서는 뷰를 구성하는데 있어서, 필요한 각종 환경 설정과 관련된 정보를 EnvironmentValue타입으로 저장한다.
- colorScheme, timeZone, locale, calendar, layoutDirection, sizeCategory, undoManager 등 다양한 속성을 가지고 있다.
Environment란
environment 어노테이션(@Environment) 은, 위의 EnvironmentValue를 프로퍼티로 가지고 있는, 구조체이다. 해당 Environment를 통해서 설정에 있는, 뷰의 환경 변수를 가져와서 사용할수 있게 된다.
EnvironmentValue와 Environment의 상관관계
즉, EnvironmentValue란, Environment구조체 안에 들어가는 뷰의 환경설정을 세팅할수있는 쓰기전용 타입.
Environment란, EnvironmentValue를 가지고 있으며, 읽기전용 구조체이다.
따라서, 환경변수를 Environment를 통해서 쉽게 관리하게 된다.
import SwiftUI
struct Theme {
static func myBackgroundColor(forScheme scheme: ColorScheme) -> Color {
let lightColor = Color.init(hex: "F2F2F7")
let darkColor = Color.init(hex: "1E1E1E")
switch scheme {
case .light : return lightColor
case .dark : return darkColor
@unknown default: return lightColor
}
}
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ 사용예
@Environment(\.colorScheme) var scheme
Theme.myBackgroundColor(forScheme: scheme)
// 이렇게 하면, dark인지 light인지에 따라서, 리턴되는 color가 바뀐다.
EnvironmentObject
EnvironmentObject는 상위뷰에서 하위뷰 전체로 데이터를 전달해줄때, 모든 하위뷰에서 상단뷰가 넘겨주는 데이터를 받게 될때 사용하게 된다. 즉 주입식 싱글톤이라고 생각하면 좀 쉽다.
EnvironmentObject를 사용하는 방법은 다음과 같다.
1. EnvironmentObject생성 (ObservableObject)
먼저 ObservableObject를 생성한다. (전체 뷰에서 해당 데이터가 변경되는것을 통해서 화면이 변경되어야 하는 부분이 있다면 해당 데이터는 Published로 감싸준다. )
class EnvironmentData: ObservableObject {
@Published var number: Int = 0
}
2. 해당 데이터를 가지고 있을 최상단뷰에서 StateObject로 객체생성
struct ContentView: View {
@State var someValue: Int = 1
@StateObject var environmentData = EnvironmentData()
var body: some View {
NavigationView {
VStack {
Text("hi")
Text("\(environmentData.number)")
Button("change!") {
environmentData.number += 1
}
NavigationLink("goNextButton") {
NextView().environmentObject(environmentData)
}
}
}
}
}
3. 데이터 받는 뷰에서 EnvironmentObject 변수 생성
struct NextView: View {
@EnvironmentObject var environmentData: EnvironmentData
var body: some View {
VStack {
Text("nextPage")
Text("\(environmentData.number)")
NavigationLink("goEnd") {
EndView().environmentObject(environmentData)
}
}
}
}
4. 데이터 전달 ( .environmentObject(_ object: ) )
NextView().environmentObject(environmentData)
EnvironmentObject 왜쓸까?
결국 보면, StateObject와 Binding으로 모든걸 해결할수 있어보인다.
혹은 객체의 경우에는 ObservedObject를 통해서 모든값을 사용할수 있어 보이지만,
EnvironmentObject는 하나의 뷰 안에서 여러개의 하위 뷰들을 사용하고, 해당 하위뷰에서 최상단 부모뷰가 가지고 있는 데이터를 공유할때 유용하다.
다음과 같은 예제를 보면 이해하기 쉽다.
struct ContentView: View {
@State var someValue: Int = 1
@StateObject var environmentData = EnvironmentData()
var body: some View {
NavigationView {
VStack {
Text("hi")
Text("\(environmentData.number)")
Button("change!") {
environmentData.number += 1
}
NextView()
EndView()
}.environmentObject(environmentData)
}
}
}
여기에서 만약 ObservedObject를 사용하게 되면 NextView().environmentObject()나, NextView(environentData: )등 코드가 굉장히 길고 귀찮다.
하지만 environment를 사용하면 코드가 굉장히 쉽고 깔끔하다.
이럴때 쓰는듯? 뇌피셜입니다.
정리
- Environment는 환경변수 값을 가지는 구조체로, 다양한 뷰에 관련된 환경변수를 가지고 있고 읽기전용이다.
- EnvironmentValue는 다양한 환경변수 값을 의미하며 Environment의 프로퍼티이다.
- EnvironmentObject는 전역적으로 데이터를 전달해서 사용하기 위한 레퍼속성이다.
Uploaded by N2T