【问题标题】:Main Thread & Collectionview.reloadData()主线程和 Collectionview.reloadData()
【发布时间】:2021-03-07 13:00:27
【问题描述】:

我有这样一种情况,代码更改了它的 collectionView 数据源,然后多次调用reloadData(),我认为这会导致我的应用程序由于竞争条件而崩溃,因为数据源变化非常快,所以我包装了 sn- p 的代码(更改数据源然后重新加载集合视图)与DispatchQueue.main.async 并且崩溃消失了。 所以这个问题是否有意义并解决了竞争条件,我的理解是用DispatchQueue.main.async 包装这个sn-p 代码在reloadData() 函数完成之前不会再次执行这个sn-p,对吗? 如果您对如何解决此问题有任何其他想法,那就太好了

更新:

例如,如果我们在主线程

上有这段代码
self.collectionView.dataSource = self.dataSource
self.collectionView.reloadData()

这个sn-p代码一个接一个地快速调用了两次,所以数据源在第一次重新加载时发生了变化, 作为一种解决方案,我用 async block 包装了这段代码的 sn-p,以确保在第一次重新加载完成之前数据源不会改变。像下面这样:

DispatchQueue.main.async {
       self.collectionView.dataSource = self.dataSource
       self.collectionView.reloadData()
}

这是否会保证数据源在reloadData() 完成之前不会更改?

【问题讨论】:

    标签: swift uicollectionview reloaddata dispatch-queue


    【解决方案1】:

    reloadData 应该总是在主线程上调用。如果你不这样做,就是崩溃。

    好的,但现在让我们谈谈数据的更改和对reloadData 的调用是如何耦合的。或许你有这样的情况:

    background queue:
    =================
        <networking>
        update the data
        main queue:
        ===========
            reloadData
    

    您仍然会遇到麻烦,因为虽然对主队列的两次调用不能重叠,但对后台队列的两次调用可以重叠,因为它可能是一个并发队列。所以这就是你的比赛条件;数据的更新和数据的重新加载是分离的。请记住,在重新加载数据期间会调用多个数据源方法,因此它们都需要查看相同数据,否则如果数据不一致,您确实会崩溃通话之间的变化。有了这种架构,这是一个非常现实的可能性。

    但是如果后台队列是一个串行队列,并且如果到主队列的步骤来自那个串行队列,那么这种重叠,至少是不可能的。所以这将是一个更安全的解决方案:

    background queue:
    =================
        <networking>
        single background *serial* queue:
        =================================
            update the data
            main queue:
            ===========
                reloadData
    

    尽管如此,我们仍然处于“共享数据”的状态。危险依然存在。没有什么可以阻止数据同时在一些other队列上被触及。为了防止这种情况发生,您需要围绕每次对数据的访问编写代码,确保访问只发生在一个队列上。毕竟,您的数据结构本身可能不是线程安全的!但是我们已经知道数据源方法将只能在主线程上查看数据,因为reloadData 就是这样工作的。所以最简单的方法就是制定一个规则,每次对数据的访问都发生在主队列上:

    background queue:
    =================
        <networking>
        main queue:
        ===========
            update the data
            reloadData
    

    因此,总而言之,如果这就是您现在正在做的事情,那么这是正确的做法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-20
      • 1970-01-01
      • 1970-01-01
      • 2017-04-08
      • 2017-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多