ios 在 UICollectionView 上调用 reloadData 后 contentSize 不会更新
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19103333/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
contentSize is not updated after reloadData is called on UICollectionView
提问by Reid Main
Does anyone know why contentSize is not updated immediately after reloadData is called on UICollectionView?
有谁知道为什么在 UICollectionView 上调用 reloadData 后没有立即更新 contentSize?
If you need to know the contentSize the best work around I've found is the following:
如果您需要知道 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.
});
Obviously this is a fairly brittle hack that makes assumptions on Apple's implementation but so far it has proven to work quite reliably.
显然,这是一个相当脆弱的 hack,它对 Apple 的实现进行了假设,但到目前为止,它已被证明是非常可靠的。
Does anyone have any other workarounds or knowledge on why this happens? I'm debating submitting a radar because this I can't understand why they cannot calculate the contentSize in the same run loop. That is how UITableView has worked for its entire implementation.
有没有人有任何其他解决方法或有关为什么会发生这种情况的知识?我正在辩论提交雷达,因为我不明白为什么他们不能在同一个运行循环中计算 contentSize。这就是 UITableView 在其整个实现中的工作方式。
EDIT: This question use to reference the setContentOffset method inside the block because I want to scroll the collection view in my app. I've removed the method call because peoples' answers focused on why wasn't I using scrollToItemAtIndexPath inside of why contentSize is not being updated.
编辑:这个问题用于引用块内的 setContentOffset 方法,因为我想在我的应用程序中滚动集合视图。我已经删除了方法调用,因为人们的答案集中在为什么我没有使用 scrollToItemAtIndexPath 里面为什么 contentSize 没有被更新。
回答by Clement T
To get the content size after reload, try to call collectionViewContentSize
of the layout object. It works for me.
要在重新加载后获取内容大小,请尝试调用collectionViewContentSize
布局对象。这个对我有用。
回答by almas
This worked for me:
这对我有用:
[self.collectionView.collectionViewLayout invalidateLayout];
[self.collectionView.collectionViewLayout prepareLayout];
回答by brodney
Edit: I've just tested this and indeed, when the data changes, my original solution will crash with the following:
编辑:我刚刚对此进行了测试,确实,当数据发生变化时,我的原始解决方案将因以下原因崩溃:
"Invalid update: invalid number of items in section 0. The number of items contained in an existing section after the update (7) must be equal to the number of items contained in that section before the update (100), plus or minus the number of items inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out)."
“无效更新:第 0 节中的项目数无效。更新后现有节中包含的项目数 (7) 必须等于更新前该节中包含的项目数 (100),加上或减去从该部分插入或删除的项目数(插入 0 个,删除 0 个),加上或减去移入或移出该部分的项目数(0 个移入,0 个移出)。”
The right way to handle this is to calculate the insertions, deletions, and moves whenever the data source changes and to use performBatchUpdates around them when it does. For example, if two items are added to the end of an array which is the data source, this would be the code:
处理这个问题的正确方法是在数据源发生变化时计算插入、删除和移动,并在发生变化时使用 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.
}];
Below is the edited solution of my original answer provided by Kernix which I don't think is guaranteed to work.
以下是 Kernix 提供的我的原始答案的编辑解决方案,我认为它不能保证有效。
Try performBatchUpdates:completion: on UICollectionView. You should have access to the updated properties in the completion block. It would look like this:
在 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.
}];
回答by Robert Mao
Call prepareLayout first, and then you will get correct contentSize:
先调用prepareLayout,然后你会得到正确的contentSize:
[self.collectionView.collectionViewLayout prepareLayout];
回答by da1
In my case, I had a custom layout class that inherits UICollectionViewFlowLayout
and set it only in the Interface Builder. I accidentally removed the class from the project but Xcode didn't give me any error, and the contentSize
of the collection view returned always zero.
就我而言,我有一个自定义布局类,UICollectionViewFlowLayout
它仅在 Interface Builder中继承和设置它。我不小心从项目中删除了这个类,但 Xcode 没有给我任何错误,并且contentSize
集合视图的 总是返回零。
I put back the class and it started working again.
我放回了课程,它又开始工作了。