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

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/