<h1><center> SwiftUI View Rendering (2) </center></h1>
###### title: `SwiftUI View Rendering(2)`
###### tags: `💻 TIL`, `Learning SwiftUI`
###### date: `2023-12-08T10:39:33.284Z`
> [color=#724cd1][name=데릭]
> [SwiftUI View Lifecycle - Vadim Bulavin](https://www.vadimbulavin.com/swiftui-view-lifecycle/)
> [Thinking in SwiftUI](https://www.objc.io/books/thinking-in-swiftui/)
> [The SwiftUI render loop - Rens Breur](https://rensbr.eu/blog/swiftui-render-loop/)
> [Exploring SwiftUI 3: View Hierarchies and State Updates - Benedict Quinn](https://blog.scottlogic.com/2020/01/28/Exploring-SwiftUI-3-View-Updates.html)
> [Understanding View Rendering Cycle in SwiftUI - azamsharp(YouTube)](https://www.youtube.com/watch?v=imiKAwYTX6s)
> [SwiftUI’s relationship to UIKit and AppKit - WWDC by Sundell](https://wwdcbysundell.com/2019/swiftui-relationship-to-uikit-appkit/)
> [Advanced Graphics and Animations for iOS Apps - WWDC NOTES by Federico Zanetello](https://www.wwdcnotes.com/notes/wwdc14/419/)
> [블로그 - Coden](https://velog.io/@ictechgy/SwiftUI%EC%9D%98-View-%EB%A0%8C%EB%8D%94%EB%A7%81%EC%9D%80-%EC%96%B8%EC%A0%9C-%EC%9D%B4%EB%A3%A8%EC%96%B4%EC%A7%80%EB%8A%94%EA%B0%80)
## 개요
> SwiftUI View Rendering(1)에 이어서 2에서는 Lifecylce에 대해서 공부해보자.
## SwiftUI View Lifecycle
> SwiftUI에서 View가 생성되고 소멸되는 과정이 어떤 이벤트를 통해 일어나는지 확인해보자.
주요 단계로는 세 가지의 Lifecycle을 가지고 있다.
`Appearing`, `Updating`, `Disappearing`

이 세 단계를 제외하고 Layout, Commit이라는 단계가 렌더링 단계에 있다.
## Appearing
Appearing은 뷰를 뷰 그래프에 넣는다는 의미이다.
이 단계에서 뷰는 뷰 초기화, State에 구독, First Rendered를 하게 된다.
아래에서 더욱 자세히 설명하겠다.

1. 초기화 시 뷰는 State에 연결되지 않는다. `SwiftUI View Rendering (1)`에서 설명했듯이 SwiftUI는 뷰를 저렴하게 구성하기 위해 전체 뷰 계층구조를 미리 구축한다.
2. 초기화 이후, 뷰는 State에 연결된다.(body가 계산되기 전에)
3. View의 body가 처음으로 호출된다.
4. 뷰 그래프가 업데이트 되고 변경 사항을 렌더링 하게 된다.
5. `onAppear()`메서드(top-down식: 부모뷰에서 자식뷰로)가 호출된다.
## Updating
Updating은 외부 이벤트나 State 변경에 대한 응답을 수행한다.
**NOTE**
> External event는 외부 변경 사항을 나타내는 단일 추상화인 Combine publisher를 의미한다.

1. User Action으로 인해 State가 변경되거나 `View.onReceive()`메서드를 통해 Observed된 Pulisher가 방출한 데이터를 감지한다.
2. AView가 변경된 State를 가지거나 외부 이벤트를 받은 경우, 이 뷰의 모든 하위 항목을 이전에 기록된 Snapshot과 비교한다.
- 이 시점에서, 뷰를 Equatable Protocol을 채택시켜 EquatableView로
3. SwiftUI는 변경된 뷰를 무효화 시킵니다. (?)
- State Value 값이 변경되면 뷰는 해당 value의 appearance를 무효화 하고 다시 body 값을 계산한다는 의미이다.
4. View 그래프를 업데이트 하고 무효화 된 뷰들을 렌더링 합니다. 그리고 모든 수정 사항들은 뷰 계층구조를 통해 top-down 방식으로 흐르게 됩니다.
상태에 연결된 뷰만 Custom Equality Implementation을 제공할 수 있다(?). State에 연결되지 않은 뷰는 항상 다시 Rendering된다.
중요한 점은 State를 뷰 계층구조 아래로 push하면 State가 변경될 때 무효화되고 다시 렌더링 되는 뷰 수가 줄어든다는 점이다.
## Disappearing
Disappearing은 계층구조에서 뷰를 제거하는 것을 의미한다.

`onDisappear()` 메서드는 뷰가 계층에서 제거된 후에 호출된다. `onAppear()`, `onDisappear()`는 top-down 방식으로 호출된다는 점이 유사하다.
## Layout & Commit Phase
**Layout Phase**
Layout 단계에서 SwiftUI는 비렌더링 뷰 계층 구조를 초기화하고, 프레임을 계산하고, 뷰를 State에 연결하고, 화면에 커밋될 diffs를 계산한다.
Layout 단계는 반드시 pure해야 하는데, pure하지 않은 코드는 runtime에서 에러를 발생시킨다.
```swift
struct ContentView: View {
@State var count = 0
var body: some View {
count += 1 // ❌ side effect
...
}
}
```
**Error**
```
Modifying state during view update, this will cause undefined behavior.
```
**Commit Phase**
Commit 단계에서 SwiftUI는 렌더링 뷰 계층구조를 업데이트하고 화면의 모든 변경 사항을 커밋하며, 더 이상 필요하지 않은 모든 뷰를 삭제한다.