State는 View의 내부 정보를 저장하고 싶을 때, State의 값이 변경되었을 때 View를 즉시 업데이트 하고 싶을 때 사용한다.
Binding은 State로부터 값을 받고, 이 값을 바꾸었을 때 기존 State도 같이 바뀌도록 하고 싶을 때 사용한다.
위 State와 Binding은 View 내에서 사용한다. 외부에서 같은 동작이 일어나도록 하고 싶으면 ObservableObject와 ObservedObject를 사용한다.
ObservableObject내에 notification을 받고 싶은 property를 Published로 선언한다. 또한, 주의해야 할점은 ObservedObject의 초기화가 View의 initializer에서 일어나야 한다는 것이다. 그렇게 하지 않으면 rerendering이 일어날 때마다 매번 새로 초기화될 수 있다. 이에 대한 해결로 iOS14에서 StateObject가 새로 나왔다. StateObject는 rerendering이 일어날 때 새로 초기화되지 않는다.
Parent와 바로 아래 children의 관계라면 Binding을 사용하는 것이 보통이다. 그러나, 만약 한창 아래의 view 계층에 있는 view에 environment를 전달하고 싶으면 EnvironmentObject를 사용한다. 상위의 view에서 .environmentObject(value)를 호출해주면 그 view 이하의 view에서 EnvironmentObject의 선언을 통해 값을 사용할 수 있다.
또는, EnvironmentKey를 사용한다. custom EnvironmentKey를 선언하고 EnvironmentValues에 관련 값의 get/set을 구현한다. 이 값은 아래와 같은 식으로 사용한다.
// EnvironmentValue에 선언된 값이 theme인 경우
@Environment(\.theme)
EnvironmentObject는 상위 view에서 값을 지정해주지 않으면 런타임에 크래시가 일어나고 EnvironmentKey는 컴파일 타임에 초기값을 지정해 주어야 하는 차이가 있다.
List에 Binding 사용하기
TabView와 NavigationView 에서 EnvironmetObject등 사용하기
View가 observe 하는 방식
Model - View 간의 연결에 Model을 변환해야 하는 경우
: View는 정렬이 된 item list가 필요하다.
1. item 리스트가 필요할 때마다 원 모델을 정렬한다.
- 값이 필요할 때마다 정렬을 하게 된다.(불필요한 작업이 될 수 있다.)
2. View 생성시 정렬된 item 리스트를 가지고 있는다.
- rerendering 마다 정렬이 새로 이루어진다.
3. ViewModel 안에 정렬된 item 리스트를 넣어둔다. 원 모델 변경시 마다 정렬된 item 리스트를 전달할 수 있다.
View 를 dismiss 하는 방법
1. @State와 @Binding 의 연결을 통한 isPresented 값 변경
2. @Environment(\.presentationMode) var presentationMode 의 사용
3. @Environment(\.dismiss) private var dismiss 의 사용
- dismiss는 callAsFunction 이다.