60

有谁知道为什么在 UICollectionView 上调用 reloadData 后没有立即更新 contentSize?

如果您需要知道 contentSize,我发现的最佳解决方法如下:

[_collectionView reloadData];

double delayInSeconds = 0.0001;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(DISPATCH_TIME_NOW, dispatch_get_main_queue(), ^(void)
    {
        // TODO: Whatever it is you want to do now that you know the contentSize.
    });

显然,这是一个相当脆弱的 hack,它对 Apple 的实施做出假设,但到目前为止,它已被证明非常可靠地工作。

有没有人知道为什么会发生这种情况?我正在辩论提交雷达,因为我不明白为什么他们不能在同一个运行循环中计算 contentSize。这就是 UITableView 在其整个实现中的工作方式。

编辑:这个问题用于引用块内的 setContentOffset 方法,因为我想在我的应用程序中滚动集合视图。我删除了方法调用,因为人们的答案集中在为什么我没有在 contentSize 没有更新的原因中使用 scrollToItemAtIndexPath。

4

6 回答 6

82

要获取重新加载后的内容大小,请尝试调用collectionViewContentSize布局对象。这个对我有用。

于 2014-02-12T03:27:20.727 回答
14

这对我有用:

[self.collectionView.collectionViewLayout invalidateLayout];
[self.collectionView.collectionViewLayout prepareLayout];
于 2015-04-20T22:19:47.307 回答
8

编辑:我刚刚对此进行了测试,实际上,当数据更改时,我的原始解决方案将崩溃​​并出现以下情况:

“无效更新:第0节中的项目数无效。更新后现有节中包含的项目数(7)必须等于更新前该节中包含的项目数(100),加上或减去从该部分插入或删除的项目数(0 插入,0 删除)加上或减去移入或移出该部分的项目数(0 移入,0 移出)。

处理这个问题的正确方法是在数据源发生变化时计算插入、删除和移动,并在发生变化时围绕它们使用 performBatchUpdates。例如,如果将两项添加到作为数据源的数组的末尾,则代码如下:

NSArray *indexPaths = @[indexPath1, indexPath2];
[self.collectionView performBatchUpdates:^() 
{
    [self.collectionView insertItemsAtIndexPaths:indexPaths];
} completion:^(BOOL finished) {
    // TODO: Whatever it is you want to do now that you know the contentSize.
}];

以下是 Kernix 提供的我的原始答案的编辑解决方案,我认为它不能保证有效。

在 UICollectionView 上尝试 performBatchUpdates:completion:。您应该可以访问完成块中的更新属性。它看起来像这样:

[self.collectionView reloadData];
[self.collectionView performBatchUpdates:^() 
{

} completion:^(BOOL finished) {
    // TODO: Whatever it is you want to do now that you know the contentSize.
}];
于 2013-10-12T21:50:35.737 回答
1

打电话后

[self.collectionView reloadData];

用这个:

[self.collectionView setNeedsLayout];
[self.collectionView layoutIfNeeded];

那么你可以得到真正的contentSize

于 2021-06-02T06:01:43.240 回答
-3

先调用prepareLayout,然后你会得到正确的contentSize:

[self.collectionView.collectionViewLayout prepareLayout];
于 2014-05-16T01:56:22.923 回答
-3

在我的例子中,我有一个自定义布局类,UICollectionViewFlowLayout它只在 Interface Builder 中继承和设置它。我不小心从项目中删除了该类,但 Xcode 没有给我任何错误,并且contentSize集合视图的返回始终为零。

我把课放回去了,它又开始工作了。

于 2019-10-31T14:55:15.043 回答