我正在關注斯坦福大學的 CS193p 開發 iOS 應用程式在線課程。
它使用 Grand Central Dispatch (GCD) API 進行多執行緒演示。但他們指出,
“自 WWDC 2021 起,GCD 大部分已被 Swift 新的內置異步 API 取代”。
所以我想了解 Lecture 中的代碼在更新它以使用這個新 API 后會是什么樣子。
在觀看了 Apple 的 WWDC 視頻后,在我看來
DispatchQueue.global(qos: .userInitiated).async { },這個新的異步 API 中的Task { }或被替換了Task(priority: .userInitiated) {},但我不確定,DispatchQueue.main.async { }替換的是什么?
所以,我的問題是:
- 我是否正確假設,
DispatchQueue.global(qos: .userInitiated).async { }已被替換為Task(priority: .userInitiated) {} - 被什么
DispatchQueue.main.async { }取代了?
請幫忙,我想學習這個新的 async-await API。
這是講座中的代碼,使用舊的 GCD API:
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!)
}
// L12 note failure if we couldn't load background image
if self?.backgroundImage == nil {
self?.backgroundImageFetchStatus = .failed(url)
}
}
}
}
整個函式(以防您需要查看更多代碼):
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!)
}
// L12 note failure if we couldn't load background image
if self?.backgroundImage == nil {
self?.backgroundImageFetchStatus = .failed(url)
}
}
}
}
case .imageData(let data):
backgroundImage = UIImage(data: data)
case .blank:
break
}
}
uj5u.com熱心網友回復:
如果你真的打算做一些緩慢而同步的事情,Task.detached這更接近于 GCD 調度到全域佇列。如果您只是使用Task(priority: ...) { ... }它,則由并發系統自行決定在哪個執行緒上運行它。(并且僅僅因為您指定了較低的值priority并不能保證它可能不會在主執行緒上運行。)
例如:
func fetchAndUpdateUI(from url: URL) {
Task.detached { // or specify a priority with `Task.detached(priority: .background)`
let data = try Data(contentsOf: url)
let image = UIImage(data: data)
await self.updateUI(with: image)
}
}
如果您想在主執行緒上進行 UI 更新,而不是將其分派回主佇列,您只需將@MainActor修飾符添加到更新 UI 的方法中:
@MainActor
func updateUI(with image: UIImage?) async {
imageView.image = image
}
話雖如此,這是一個非常不尋常的模式(同步執行網路請求并創建一個分離的任務以確保您不會阻塞主執行緒)。我們可能會使用URLSession的新異步data(from:delegate:)方法來異步執行請求。
簡而言之,與其為舊的 GCD 模式尋找一對一的類似物,不如盡可能使用 Apple 提供的并發 API。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/363661.html
上一篇:如何自動啟動依賴于按鈕的影片?
