Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- SF Symbols 3.0
- ProRAW
- WWDC 2021
- METAL
- Hand Pose Detect
- Xcode Cloud
- concurrency
- AppleEvent
- async
- DriverKit
- NSUserActivity
- SWiFT
- App Clip
- MDM
- AVFoundation
- detent
- Hand Action Detect
- CoreML
- Reality Composer
- Object Capture
- SF Symbols
- AR Quick Look
- profile
- actor
- Xcode Organizer
- Physical Audio
- User Enrollment
- swiftUI
- Mac
- DooC
Archives
- Today
- Total
nyancoder
WWDC 2021 - Discover concurrency in SwiftUI 본문
원본 영상: https://developer.apple.com/videos/play/wwdc2021/10019/
Concurrent data models
- 이 예제에서는 SwiftUI를 사용하여 우주 사진을 다운로드하는 앱을 볼 것입니다.
- 데이터 모델로는 SpacePhoto 구조체를 사용하여 이미지에 대한 정보를 저장합니다.
- 구조체에는 제목, 설명, 이미지가 게시된 날짜, 이미지 URL과 같은 필드가 있습니다.
- 서버 응답에서 인스턴스를 만들거나, 디스크에 저장할 수 있도록 Codable로 만듭니다.
- ForEach 및 기타 데이터 기반 View에서 사용할 수 있도록 Identifiable로 만듭니다.
- 사진의 목록을 표시하기 위해서 컬렉션을 가져와 보관할 Photos 클래스를 모델로 사용합니다.
- Photos 클래스는 ObservableObject를 구현하여, SwiftUI View가 데이터가 업데이트될 때마다 자동으로 업데이트됩니다.
- Published 속성을 사용하여 SpacePhotos 배열을 저장하고 있습니다.
- PhotoView는 제목을 표시합니다.
- CatalogView는 사진 목록이 표시됩니다.
- List에서 ForEach를 사용하여 각 사진에 대한 PhotoView를 표시합니다.
- SwiftUI가 ObservableObject와 상호작용하는 방식은 "run loop"라고 불리는 라이프 사이클을 통해서 이루어집니다.
- run loop는 사용자로부터 이벤트를 수신하고, 모델을 업데이트할 수 있도록 한 다음, SwiftUI View에 렌더링 합니다.
- 이러한 한 번의 업데이트를 "Run loop tick"이라고 부를 수 있습니다.
- Photos객체를 예로 들면, updateItems를 호출하고 주 액터에서 실행됩니다.
- "items"는 Published 속성이므로 값이 변경되면 objectWillChange 이벤트를 전달한 뒤 "items"에 보관됩니다.
- SwiftUI가 objectWillChange를 보면, 스냅숏을 만들고 run loop의 다음 틱에서 스냅숏을 현재 값과 비교합니다.
- 값이 다른 경우 SwiftUI는 View를 업데이트합니다.
- objectWillChange, 저장소 업데이트, 실행 루프 틱이 모두 Main Actor에서 발생하기 때문에 순서대로 발생하는 것이 보장됩니다.
- 모델 코드가 너무 많은 작업을 수행하는 경우 업데이트가 느려질 수 있습니다.
- 예를 들어 fetchPhotos함수에서 다운로드가 완료되기를 기다리고 있으면 run loop tick의 호출을 막고 있기 때문에 업데이트가 일어나지 않아 멈춘 것처럼 보입니다.
- 또 다른 경우는 DispatchQueue를 통해서 다른 스레드에서 fetchPhotos를 수행하고 아이템을 업데이트하는 경우가 있습니다.
- 이 경우는 objectWillChange가 run loop tick 직전에 호출되어 SwiftUI가 스냅숏의 변경을 알아채지 못하여 UI가 업데이트되지 않을 수 있습니다.
- 올바르게 업데이트가 되려면, SwiftUI는 objectWillChange, ObservableObject 업데이트, run loop tick의 순서로 이루어져야 합니다.
- Swift 5.5 이전과 달리 상태를 업데이트하기 위해서 단순히 await만 호출하면 됩니다.
- updateItems에서 fetchPhotos를 비동기로 호출하기 위해 해당 함수를 async로 만듭니다.
- 그다음 fetchPhotos 또한 async 함수로 구성하고 호출 지점에 await를 붙여줍니다.
- 이 과정에서 결과의 업데이트가 Main Thread에서 이루어지는 것을 보장할 수 있도록 @MainActor를 class에 적용합니다.
- 이제 카탈로그가 표시될 때마다 updateItems를 호출하려고 할 때, 이전에는 onAppear를 사용했습니다.
- 이제는 task함수를 이용하여 뷰 수명이 시작될 때 비동기로 작업을 호출할 수 있습니다.
- 이러한 새 함수들의 작업의 수명은 View의 수명과 연결되어 있으므로 View의 수명이 끝나면 작업이 자동으로 취소됩니다.
- AsyncImage API를 사용하면 원격 서버에서 쉽게 이미지를 로드할 수 있습니다.
- AsyncImage에서는 로딩 중에 표시할 View를 위한 placeholder함수가 있습니다.
- 또한 이미지의 로딩이 끝나면 원하는 크기로 리사이즈 작업을 처리할 수 있습니다.
- 다음 예로 이미지를 저장하는 버튼을 만들면, 비동기 작업을 수행하기 때문에 async구문으로 저장 작업을 수행합니다.
- 저장이 되고 있는 과정을 나타내기 위해서 isSaving 변수에 상태를 기록합니다.
- label 항목에서 저장 중인지 여부를 체크하여 불투명도와 ProgressView() 표시 유무를 결정합니다.
- 목록을 새로 고칠 수 있는 refreshable 함수를 통하여 비동기로 콘텐츠를 받아 업데이트할 수 있습니다.
'WWDC > WWDC 2021' 카테고리의 다른 글
Comments