【问题标题】:How to determine which NSCollectionViewItems are actually visible如何确定哪些 NSCollectionViewItem 实际可见
【发布时间】:2019-03-30 22:35:41
【问题描述】:

我正在使用NSCollectionView,它显示了我需要在后台渲染的图像。此渲染需要大量时间(例如 100 毫秒到一秒以上)。

我使用具有相同大小的NSCollectionViewItem 磁贴的常规流布局 (NSCollectionViewFlowLayout)。

collectionView 上线后,它会创建比实际适合当前视图更多的项目实例(图块)。例如,如果 6 个图块适合视图,则它要求大约 20 个图块。我为每个创建的图块启动一个渲染过程。渲染图像后,图块会收到通知,这反过来会导致刷新其视图。

现在,在渲染过程中,用户可以向下滚动,例如到最后 6 个牌。这会产生性能问题:

队列中仍有许多尚未可见且短期内不可见的图块的渲染(当用户直接滚动到最后时,它们被跳过了)。 collectionView,现在请求现在可见的最后 6 个图块的视图将丢弃其先前分配的 6 个,其中 4 个可能已经被渲染并标记为丢弃,因此渲染队列中剩余的 16 个图块中只有 2 个将被通知他们将不再需要并从队列中删除。并且从末尾新可见的 6 个图块将附加到渲染队列中。

这意味着,在用户开始看到他滚动到的任何图像之前,必须再渲染 14 张图像,即使它们没有显示在当前集合视图的内容区域中。

我该如何优化它,以便当用户滚动时,我立即开始渲染最新的可见NSCollectionViewItems?没有任何委托功能似乎对此有所帮助。甚至像visibleItems 这样的函数不仅返回可见的,而且返回collectionView 分配的所有,包括14 个不可见的。

我可以在将项目添加到队列时始终将它们插入到前面,而不是将它们附加到队列的末尾。不过,这也无济于事,因为最初,当 collectionView 请求 20 个图块时,我最终会先渲染第 20 个图块,因此在渲染 14 个不可见的图块之前不会显示任何渲染。

【问题讨论】:

    标签: uikit nscollectionview


    【解决方案1】:

    -[NSCollectionView visibleItems] 的文档:

    这个数组可能包含集合视图实际可见矩形之外的项目。例如,它可能包含最近可见但已被滚动出视图的项目。要测试一个项目是否真正可见,请检查它的框架矩形是否与集合视图的 visibleRect 相交。

    所以,这里有一个执行这个测试的函数,只返回实际可见的项目:

    - (NSArray<NSCollectionViewItem*> * _Nonnull) trulyVisibleItemsInCollectionView:(NSCollectionView*)collectionView
    {
        NSMutableArray<NSCollectionViewItem*> *result = [NSMutableArray array];
        NSArray<NSCollectionViewItem *> *items = collectionView.visibleItems;
        NSRect viewRect = collectionView.visibleRect;
        for (NSCollectionViewItem *item in items) {
            if (NSIntersectsRect(item.view.frame, viewRect)) {
                [result addObject:item];
            }
        }
        return result;
    }
    

    不过,这仍然难以有效地管理渲染队列:

    1. 当我的 collectionView:itemForRepresentedObjectAtIndexPath: 被调用时,视图还没有添加到 collectionView 中,因此现在确定是否应安排此图块立即呈现还为时过早。

    2. 可以使用计时器定期检查哪些项目是可见的,并将它们移动到队列的前面。它不应该用于决定是否将项目插入队列,因为如果在创建 tile 对象后计时器过早触发,则它不会被添加到视图中,这将导致更多延迟,直到渲染开始。因此,我认为最好在知道可能需要项目后立即将它们添加到渲染器,但在明确哪些项目可见哪些不可见后重新排列队列。

    【讨论】:

      猜你喜欢
      • 2012-05-02
      • 1970-01-01
      • 2012-10-21
      • 1970-01-01
      • 2011-06-03
      • 2017-10-28
      • 2019-01-06
      • 2010-10-25
      • 1970-01-01
      相关资源
      最近更新 更多