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