如果委托已被使用,为什么我需要 manage/update 主线程

Why do I need to manage/update main thread if delegate is already being used

我有一个异步 api 调用,我正在使用委托模式并分配了一个协议方法来处理当我们收到来自 api[=13 的响应时如何处理数据=]

didWeatherUpdate

我在委托中实现了这个。按照我的理解,我用来用 api 中的数据更新 UI 的方法在异步网络请求完成之前不会触发。

我的问题是为什么需要明确告知主线程它是一个异步进程。如果在 api 调用完成后数据准备好之前不会调用该函数。我的假设是,当数据准备好时,函数将触发,然后添加到主线程处理的队列中。来自完整的堆栈背景似乎如此额外

  func didWeatherUpdate(_ weatherManager: WeatherManager,_ weather: WeatherModel){
        print("\(weather.temperature) from the controller")
        DispatchQueue.main.async{
            self.temperatureLabel.text = weather.temperatureString
        }

这是你的函数

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.