CS193p 강의의 lec 9, 10에서 GCD를 사용한 것을 new async await로 변경해보겠습니다.
먼저 강의에서 언급한 Swift's new built-in async API는 async/await를 지칭하는 것 같습니다.
2021 WWDC - Meet async/await in Swift
javascript의 async/await 구조와 매우 비슷합니다.
nest return 코드가 사라져서 가독성이 향상되었습니다.
기존 코드는 다음과 같습니다.
private func fetchBackgroundImageDataIfNecessary() {
backgroundImage = nil
switch emojiArt.background {
case .url(let url):
// fetch the url
backgroundImageFetchStatus = .fetching
DispatchQueue.global(qos: .userInitiated).async {
let imageData = try? Data(contentsOf: url)
DispatchQueue.main.async { [weak self] in
if self?.emojiArt.background == EmojiArtModel.Background.url(url) {
self?.backgroundImageFetchStatus = .idle
if imageData != nil {
self?.backgroundImage = UIImage(data: imageData!)
}
}
}
}
case .imageData(let data):
backgroundImage = UIImage(data: data)
case .blank:
break
}
}
url에서 이미지를 가져오는 것은 background queue에서 처리하도록 했습니다.
불러온 이미지를 일련의 검증로직 이후에 self?.backgroundImage라는 View에 연관된 변수를 할당합니다.
View를 변경하기 때문에 main queue에 작업을 수행하도록 했습니다.
해당 코드를 다음과 같이 변경했습니다.
private func fetchBackgroundImageDataIfNecessary_async() {
backgroundImage = nil
switch emojiArt.background {
case .url(let url):
// fetch the url
Task {
await background(url: url)
}
case .imageData(let data):
backgroundImage = UIImage(data: data)
case .blank:
break
}
}
private func background(url: URL) async {
guard let imageData = await getBackgroundImage(url: url) else { return }
await changeBackground(url: url, imageData: imageData)
}
private func getBackgroundImage(url: URL) async -> Data? {
return try? Data(contentsOf: url)
}
private func changeBackground(url: URL, imageData: Data) async {
await MainActor.run { [weak self] in
if self?.emojiArt.background == EmojiArtModel.Background.url(url) {
self?.backgroundImageFetchStatus = .idle
self?.backgroundImage = UIImage(data: imageData)
}
}
}
2가지 async 기능을 함수로 분리했습니다.
1. URL을 통해 이미지를 byte buffer 로 가져오는 것 -> getBackgroundImage(url: URL) async -> Data?
2. byte buffer의 이미지를 UI의 Image로 변경하는 것 -> changeBackground(url: URL, imageData: Data) async
UI상에서 배경 이미지 변경은 MainActor를 이용했습니다.
Main Actor는 main dispatch queue와 실행하는 역할이 동일한 singleton actor입니다.
main queue에 UI와 관련된 작업을 전달합니다.
Reference
https://www.avanderlee.com/swift/mainactor-dispatch-main-thread/
'iOS > CS193p - Developing Apps for iOS' 카테고리의 다른 글
[CS193p] Lecture 11 - Persistence에 대해서 (0) | 2021.12.28 |
---|---|
[CS193p] Assignment 4 - Animated Set 솔루션 (0) | 2021.11.19 |
[CS193p] Assignment 4 - Animated Set 문제 번역 (0) | 2021.11.16 |
[CS193p] Assignment 3 - Set Game 솔루션 (0) | 2021.11.14 |
[CS193p] Assignment 3 - Set Game 문제 번역 (0) | 2021.11.08 |