UICollectionView performBatchUpdates:如果视图需要布局,是否会意外断言? [英] UICollectionView performBatchUpdates: asserts unexpectedly if view needs layout?

查看:236
本文介绍了UICollectionView performBatchUpdates:如果视图需要布局,是否会意外断言?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我在这些方法之间从viewWillAppear:内部,viewDidAppear:内部调用-[UICollectionView performBatchUpdates:],或者在更大的UIView视图层次结构未对集合视图进行布局的任何时候,则集合视图将使用以下方式进行断言:

If I call -[UICollectionView performBatchUpdates:] from inside viewWillAppear:, inside viewDidAppear:, between these methods, or anytime the collection view has not been laid out by the greater UIView view hierarchy, the collection view will assert with:

***由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序, 原因:无效的更新:无效的部分数.区间数 更新(X)之后包含在集合视图中的数字必须等于数字 更新(X)之前或之后在集合视图中包含的部分的数量,正负

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections. The number of sections contained in the collection view after the update (X) must be equal to the number of sections contained in the collection view before the update (X), plus or minus the number of sections inserted or deleted (X inserted, 0 deleted).'

"X"是我插入的项目数.我已经确认数据源正在正确更新,并且更新中的索引路径是正确的.

Where "X" is whatever number of items I've inserted. I've confirmed that the data source is being updated properly and the index paths in the update are correct.

当刚在调用performBatchUpdates:之前更新数据源时,收集视图状态如何与数据源保持一致?似乎是某些意外触发了reloadData.

How could the collection view state become consistent with the data source, when the data source was just updated immediately before calling performBatchUpdates:? It seems something is unexpectedly triggering a reloadData.

推荐答案

UICollectionView似乎有特殊行为(一个错误?):如果需要布局,则performBatchUpdates:在调用更新块之前可以有效地充当reloadData. ,这会使您在更新块期间计划进行的任何更改都对馆藏视图簿记有害.

UICollectionView seems to have special behavior (a bug?): if it needs layout, then performBatchUpdates: effectively acts as a reloadData before calling the update block, which renders whatever changes you plan to make during the update block poisonous to the collection view bookkeeping.

如果计划在正确布局视图之前对视图进行批处理更新(例如从快速变化的数据模型环境中的通知处理程序中),则需要确保在viewWillAppear:中调用集合视图上的layoutIfNeeded.这样可以防止在对performBatchUpdates:的调用中重新加载集合视图.

If you plan to have batch updates applied to the view before it's been properly laid out (like from a notification handler in a rapidly changing data model environment for instance), you need to make sure that in viewWillAppear: that you call layoutIfNeeded on the collection view. This will prevent the collection view from reloading in the call to performBatchUpdates:.

我们通过将日志放入集合视图数据源numberOfSections方法中并发现此回溯记录以查看从何处调用该记录,来发现此行为:

We discovered this behavior by putting a log in our collection view data source numberOfSections method and printed out this backtrace to see where it was called from:

2014-11-12 15:30:06.173 CVCrasher[66830:6387719] [CV] #sections stack: (
0   CVCrasher     0x000000010ba9122d -[MyViewController numberOfSectionsInCollectionView:] + 61
1   UIKit         0x000000010cfc2811 -[UICollectionViewData _updateItemCounts] + 147
2   UIKit         0x000000010cfc4a89 -[UICollectionViewData numberOfSections] + 22
3   UIKit         0x000000010cfaebae -[UICollectionViewFlowLayout _getSizingInfos] + 348
4   UIKit         0x000000010cfafca9 -[UICollectionViewFlowLayout _fetchItemsInfoForRect:] + 526
5   UIKit         0x000000010cfab51f -[UICollectionViewFlowLayout prepareLayout] + 257
6   UIKit         0x000000010cfc2a10 -[UICollectionViewData _prepareToLoadData] + 67
7   UIKit         0x000000010cfc30e9 -[UICollectionViewData validateLayoutInRect:] + 54
8   UIKit         0x000000010cf8b7b8 -[UICollectionView layoutSubviews] + 170
9   UIKit         0x000000010c9d1973 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 521
10  QuartzCore    0x0000000110cf2de8 -[CALayer layoutSublayers] + 150
11  QuartzCore    0x0000000110ce7a0e _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
12  UIKit         0x000000010c9c5847 -[UIView(Hierarchy) layoutBelowIfNeeded] + 611
13  UIKit         0x000000010cf9c7b7 -[UICollectionView performBatchUpdates:completion:] + 164
...

在这里您可以清楚地看到,在应用更新之前,对performBatchUpdates:的调用正在访问数据源,并且与更改的模型保持一致.然后调用该块本身时,集合视图将引发一个断言,就像我在原始问题中显示的那样.

Here you can plainly see that the call to performBatchUpdates: is hitting the datasource and becoming consistent with the changed model before the updates are applied. When the block itself is then called, the collection view will throw an assert like I showed in the original question.

tl; dr -当UICollectionView需要布局时,performBatchUpdates:有效地充当对reloadData的调用,并且由于记账不正确,将使批更新块断言.呼叫viewWillAppear:中的layoutIfNeeded来避免这种情况.

tl;dr - When UICollectionView needs layout, performBatchUpdates: effectively acts as a call to reloadData and will make the batch update block assert because of bad bookkeeping. Call layoutIfNeeded in viewWillAppear: to avoid this behavior.

这篇关于UICollectionView performBatchUpdates:如果视图需要布局,是否会意外断言?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆