简体   繁体   English

UICollectionView reloadData的有趣问题

[英]Interesting issue with UICollectionView reloadData

When dealing with a UICollectionView in my app I've ran into a strange problem related to reloading data. 在我的应用程序中处理UICollectionView ,我遇到了一个与重新加载数据有关的奇怪问题。 After lot's of debugging and analyzing logs I've come to the conclusion that if reloadData is immediately followed by insertItemsAtIndexPaths the dreaded error below is guaranteed to occur: 经过大量的调试和分析日志后,我得出的结论是,如果reloadData后面紧跟insertItemsAtIndexPaths ,则保证发生下面的可怕错误:

Name: NSInternalInconsistencyException Reason: Invalid update: invalid number of items in section 0. The number of items contained in an existing section after the update (1) must be equal to the number of items contained in that section before the update (1), plus or minus the number of items inserted or deleted from that section (1 inserted) ... 名称: NSInternalInconsistencyException原因:无效更新:第0节中的项目数无效。更新后现有部分中包含的项目数(1)必须等于更新前该部分中包含的项目数(1),加上或减去从该部分插入或删除的项目数(插入1个)...

They only way for this to happen consistently is that internally the UICollectionView is still busy with reloadData when the call to insertItemsAtIndexPaths arrives. 它们只能始终如一地发生这种情况,即当对insertItemsAtIndexPaths的调用到达时, UICollectionView内部仍然忙于reloadData The fact that " collectionView:numberOfItemsInSection " is called twice in a row before the insertItemsAtIndexPaths completes seems to support this since that method is never called twice in a row in call other cases. insertItemsAtIndexPaths完成之前连续两次调用“ collectionView:numberOfItemsInSection ”这一事实似乎支持这一点,因为在调用其他情况下,该方法永远不会连续调用两次。

Has anyone seen similar behavior or can confirm my analysis or even suggest a proper workaround? 有没有人看到类似的行为或可以确认我的分析,甚至建议一个正确的解决方法?

Update : Any yes I've made sure that all relevant invocations occur on the main thread. 更新 :任何是的我确保所有相关的调用都发生在主线程上。

Update 2 : Since the reasoning behind getting into this situation at all has been questioned: I'm using Monotouch and the code in question is intended to keep generic .Net Collections firing this event into the appropriate calls to keep the UICollectionView bound to the collection in sync. 更新2 :由于完全陷入这种情况背后的推理受到质疑:我正在使用Monotouch,并且有问题的代码旨在保持通用的.Net Collections 将此事件发送到适当的调用以保持UICollectionView绑定到集合同步中。 When the source collection is cleared it reacts with a Reset action, followed by one or more Add actions when items get inserted into it which leads to the problem outlined above. 清除源集合后,它会对Reset操作作出反应,然后在项目插入其中时执行一个或多个Add操作,这会导致上述问题。 Hope this helps. 希望这可以帮助。

When you call insertItemsAtIndexPaths ( removeItemsAtIndexPaths is analogous), you are telling your collectionview that its datasource now has more items available, and that it should insert these available items at the indexpaths you specify. 当您调用insertItemsAtIndexPathsremoveItemsAtIndexPaths类似)时,您告诉您的collectionview其数据源现在有更多可用项,并且它应该在您指定的索引路径中插入这些可用项。

It checks your datasource whether that statement is true, and if it detects that the amount of old items plus the amount of items you say you inserted is not equal to the amount of new items, it says it can't do the update, as you lied about how many items you changed. 它检查您的数据源是否该语句是真的,如果它检测到旧项目的数量加上您说的插入的项目数量不等于新项目的数量,它表示它无法进行更新,如你撒谎了你改变了多少项。

Now, what you are doing is you are telling your collectionview is that it should reload all its data from its datasource (with the new data) and right after that, you tell it you inserted x items. 现在,你正在做的是你告诉你的collectionview它应该从它的数据源(使用新数据)重新加载它的所有数据,然后就告诉它你插入了x项。 That is a false statement, as you just reloaded the collectionview, which updated its amount of items, and thus the amount of items before the update is equal to the amount of items after the update (you're not doing anything), and not increased by the amount of indexpaths you specified. 这是一个虚假陈述,因为你刚刚重新加载了集合视图,它更新了它的项目数量,因此更新前的项目数量等于更新后的项目数量(你没有做任何事情),而不是增加了您指定的索引路径数量。

I hope you're still with me, because here's your solution: 我希望你还和我在一起,因为这是你的解决方案:

Remove the reloadData before the insertItemsAtIndexPaths , as this breaks its assertions and will throw exceptions when incorrectly used. insertItemsAtIndexPaths之前删除reloadData ,因为这会破坏其断言并在错误使用时抛出异常。 If you would like to reload the collectionview before inserting items, make sure you perform insertItemsAtIndexPaths right after you change the items in the datasource. 如果要在插入项目之前重新加载集合insertItemsAtIndexPaths ,请确保在更改数据源中的项目后立即执行insertItemsAtIndexPaths

Read up on the documentation for this method here . 阅读了此方法的文档上这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM