---
# System prepended metadata

title: ' SwiftUI View Rendering (2) '
tags: ["\U0001F4BB TIL", View Rendering, SwiftUI]

---

<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`

![image](https://hackmd.io/_uploads/H19_gRk8T.png)

이 세 단계를 제외하고 Layout, Commit이라는 단계가 렌더링 단계에 있다.

## Appearing

Appearing은 뷰를 뷰 그래프에 넣는다는 의미이다. 
이 단계에서 뷰는 뷰 초기화, State에 구독, First Rendered를 하게 된다.

아래에서 더욱 자세히 설명하겠다. 

![image](https://hackmd.io/_uploads/SkxPf7Ay8T.png)

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를 의미한다.

![image](https://hackmd.io/_uploads/Bk4yHRyLa.png)

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은 계층구조에서 뷰를 제거하는 것을 의미한다. 

![image](https://hackmd.io/_uploads/HJbTWpZI6.png)

`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는 렌더링 뷰 계층구조를 업데이트하고 화면의 모든 변경 사항을 커밋하며, 더 이상 필요하지 않은 모든 뷰를 삭제한다. 

