我从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/