在后台计算视图模型后更新集合视图



我从API接收特定串行队列上的数据项,用于计算要在集合视图中显示的视图模型。简化代码为:

var viewModels: [ViewModel] = []    // read and written on main queue
var _viewModels: [ViewModel] = []   // written in background, read in main queue
func didReceive(items: [Item]) {
// called on the same background serial queue
_viewModels = items.map { ViewModel($0) }
DispatchQueue.main.async {
self.viewModels = self._viewModels
self.updateCollectionView {
// UI update has finished
}
}
}

didReceive可随时调用。_viewModels总是写入同一个后台队列。之后,我切换到主队列来缓存计算视图模型,并在数据源中使用它来显示。

self.viewModels = self._viewModels会导致崩溃吗?我必须使用某种锁定机制吗?如果是,它是如何工作时,主线程涉及?

不一定会崩溃,但这会导致不一致。由于_viewModels是在didReceive的作用域之外声明的,因此它是一个共享资源,每次进入didReceive时都可以修改它。在将它分派给主线程之后,其他线程可以进入didReceive并更改您的值。所以当你把它赋值给self.viewModels时,你会得到" second "价值。

我相信在didReceive中声明_viewModels将解决您的问题,因为您将对didReceive的每次运行有一个引用:

var viewModels: [ViewModel] = []    // read and written on main queue
func didReceive(items: [Item]) {
// called on the same background serial queue
let _viewModels = items.map { ViewModel($0) }
DispatchQueue.main.async {
self.viewModels = _viewModels
self.updateCollectionView {
// UI update has finished
}
}
}

如果你不允许这样做,试着看看Actors:https://www.avanderlee.com/swift/actors/