我正在关注斯坦福大学的CS193p开发iOS应用程序在线课程。
它正在使用Grand Central Dispatch(GCD)API进行多线程演示。
“截至WWDC 2021,GCD已基本被Swift新的内置异步API所取代”。
所以我想了解一下,在更新了课程中的代码以使用这个新的API之后,它看起来会是什么样子。
看过苹果的WWDC视频后,我觉得
在这个新的异步API中,DispatchQueue.global(qos: .userInitiated).async { }
被替换为Task { }
或Task(priority: .userInitiated) {}
,但我不确定,DispatchQueue.main.async { }
被替换为什么?
所以我的问题是
1.我的假设是否正确,DispatchQueue.global(qos: .userInitiated).async { }
已替换为Task(priority: .userInitiated) {}
DispatchQueue.main.async { }
已被替换为什么?
请帮助,我想学习这个新的异步等待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
}
}
1条答案
按热度按时间njthzxwz1#
如果你真的要做一些缓慢而同步的事情,
Task.detached
更接近于GCD向全局队列的分派,如果你只是使用Task(priority: ...) { ... }
,你就把它留给并发系统来决定在哪个线程上运行它(仅仅因为你指定了一个较低的priority
并不能保证它不会在主线程上运行)。例如:
如果您想在主线程上执行UI更新,而不是将其调度回主队列,则只需将
@MainActor
修饰符添加到更新UI的方法中:尽管如此,这是一个非常不寻常的模式(同步处理网络请求并创建一个分离的任务以确保不会阻塞主线程)。我们可能会使用
URLSession
的新异步方法data(from:delegate:)
来异步执行请求。它提供了更好的错误处理,更好的可配置性,参与结构化并发,并且是可取消的。简而言之,不要为旧的GCD模式寻找一对一的类似物,而是尽可能使用Apple提供的并发API。
FWIW,除了上面显示的
@MainActor
模式(作为分派到主队列的替代),您还可以执行以下操作:这大致类似于向主队列的调度。在WWDC 2021视频Swift concurrency: Update a sample app中,他们说:
在Swift的并发模型中,有一个全局参与者叫做main actor,它负责协调主线程上的所有操作,我们可以把我们的
DispatchQueue.main.async
替换成MainActor
的run
函数调用,这需要在MainActor
上运行一段代码......但他接着说:
我可以用
@MainActor
注解函数,这要求调用者在函数运行之前切换到主参与者。......现在我们已经将此函数放在主参与者上,严格地说,我们不再需要MainActor.run
。