我有一个异步 api 调用,我正在使用委托模式并分配了一个协议方法来处理当我们收到来自 api 的响应时如何处理数据
didWeatherUpdate
我在委托中实现了这一点。我理解它的方式,在异步网络请求完成之前,我用来使用来自 api 的数据更新 UI 的这种方法不会触发。
我的问题是为什么需要明确告诉主线程它是一个异步进程。如果在api调用完成后数据准备好之前不会调用该函数。我的假设是,当数据准备好时,函数会触发,然后添加到主线程工作的队列中。从完整的堆栈背景来看,这似乎是额外的
func didWeatherUpdate(_ weatherManager: WeatherManager,_ weather: WeatherModel){
print("\(weather.temperature) from the controller")
DispatchQueue.main.async{
self.temperatureLabel.text = weather.temperatureString
}
回答1
这是你的功能
func didWeatherUpdate(_ weatherManager: WeatherManager,_ weather: WeatherModel){
print("\(weather.temperature) from the controller")
DispatchQueue.main.async{
self.temperatureLabel.text = weather.temperatureString
}
}
此函数在后台线程上调用。 print
行在该线程上完成。
如果您尝试将 self.temperatureLabel.text = weather.temperatureString
作为下一行而不将其包装在 DispatchQueue
异步块中,那么它将立即在后台运行并导致运行时警告,因为您不允许在后台更新 UI。
要更新 UI,您需要将您的行包装在一个块中并将其发送到主队列而不是等待它。这正是它的作用
DispatchQueue.main.async {
self.temperatureLabel.text = weather.temperatureString
}
这里的 async
没有告诉主队列数据获取是异步的。意思是您希望将块异步发送到主队列,而不是让后台线程等待 UI 更新。如果你在这之后有一个 print
行,它可能发生在 UI 更新之前。
如果您希望后台线程等待 UI,您将使用 DispatchQueue.main.sync
。