use*_*170 26 grand-central-dispatch async-await swift
我正在关注斯坦福大学的 CS193p 开发 iOS 应用程序在线课程。
它使用 Grand Central Dispatch (GCD) API 来演示多线程。但他们指出,
“自 WWDC 2021 起,GCD 已大部分被 Swift 新的内置异步 API 取代”。
因此,我想了解讲座中的代码在更新以使用这个新 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)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
整个函数(如果您需要查看更多代码):
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)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Rob*_*Rob 31
如果您确实要做一些缓慢且同步的事情,Task.detached则更接近于 GCD\xe2\x80\x99s 调度到全局队列。如果您只是使用Task(priority: ...) { ... }它,则将其留给并发系统自行决定在哪个线程上运行它。(仅仅因为您指定了较低的值priority并不能保证它不会在主线程上运行。)
例如:
\nfunc fetchAndUpdateUI(from url: URL) {\n Task.detached { // or specify a priority with `Task.detached(priority: .background)`\n let data = try Data(contentsOf: url)\n let image = UIImage(data: data)\n await self.updateUI(with: image)\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n如果您想在主线程上进行 UI 更新,而不是将其分派回主队列,您只需将修饰符添加@MainActor到更新 UI 的方法中即可:
@MainActor\nfunc updateUI(with image: UIImage?) async {\n imageView.image = image\n}\nRun Code Online (Sandbox Code Playgroud)\n话虽如此,这是一种非常不寻常的模式(同步执行网络请求并创建一个分离的任务以确保不会阻塞主线程)。我们可能会使用URLSession\xe2\x80\x99s 新的异步data(from:delegate:)方法来异步执行请求。它提供更好的错误处理、更好的可配置性、参与结构化并发并且是可取消的。
简而言之,与其寻找旧 GCD 模式的一对一模拟,不如尽可能使用 Apple 提供的并发 API。
\nFWIW,除了@MainActor上面显示的模式(作为调度到主队列的替代)之外,您还可以执行以下操作:
await MainActor.run {\n \xe2\x80\xa6\n}\nRun Code Online (Sandbox Code Playgroud)\n这大致类似于调度到主队列。在 WWDC 2021 视频Swift 并发:更新示例应用程序中,他们说:
\n\n\n在 Swift\xe2\x80\x99s 并发模型中,有一个称为主参与者的全局参与者,它协调主线程上的所有操作。我们可以将 our 替换为对\xe2\x80\x99s函数
\nDispatchQueue.main.async的调用。这需要一段代码才能在. \xe2\x80\xa6MainActorrunMainActor
但他接着说:
\n\n\n我可以用 注释函数
\n@MainActor。这将要求调用者在运行该函数之前切换到主要参与者。\xe2\x80\xa6 既然我们已经把这个功能放在了主角身上,严格来说,我们就MainActor.run不再需要这个了。
| 归档时间: |
|
| 查看次数: |
18570 次 |
| 最近记录: |