在后台计算视图模型后更新集合视图
Update collection view after computing view models in background
我在特定的串行队列上从我的 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([=10=]) }
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
时,您将获得“第二个”值。
我相信在 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([=10=]) }
DispatchQueue.main.async {
self.viewModels = _viewModels
self.updateCollectionView {
// UI update has finished
}
}
}
如果不允许您这样做,请尝试查看 Actors:
https://www.avanderlee.com/swift/actors/
我在特定的串行队列上从我的 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([=10=]) }
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
时,您将获得“第二个”值。
我相信在 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([=10=]) }
DispatchQueue.main.async {
self.viewModels = _viewModels
self.updateCollectionView {
// UI update has finished
}
}
}
如果不允许您这样做,请尝试查看 Actors: https://www.avanderlee.com/swift/actors/