I'm working on an app that has a UICollectionViewController that is crashing in certain mysterious situations that are hard to reproduce. The log for the crash looks like this:
*** Assertion failure in -[UICollectionViewData validateLayoutInRect:], /SourceCache/UIKit_Sim/UIKit-3318.16.14/UICollectionViewData.m:417 *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UICollectionView received layout attributes for a cell with an index path that does not exist: <NSIndexPath: 0xc000000000008016> {length = 2, path = 0 - 1}'
Crashes like this only seem to have started occurring in our code once we switched to the iOS 8 SDK.
Why is this happening?
Note: I already know what the answer to question is, but I found very little information relating to this crash on Stack Overflow and the rest of the web. I'll post the answer below. This bug took my coworker and I three days to track down, so hopefully this post will save someone else a lot of time and frustration. I have filed this bug with Apple.
The crash was happening in the following situation:
We had a collection view controller that was presenting another view controller on top of it.
While the collection view controller was no longer visible, the following sequence of events was occasionally occurring in response to our app's back end requests.
[UICollectionView insertItemsAtIndexPaths:]
was called with 50 items on the collection view of the hidden UICollectionViewController
.[UICollectionView reloadData]
was called on the hidden collection view.[UICollectionView reloadData]
was called again.The assertion failure in the internal UIKit class UICollectionViewData
would happen at step 6.
So, the lesson is, try to avoid manipulating a collection view that is not visible on the screen.
Our workaround for this problem was to call [UICollectionView reloadSections:]
instead of [UICollectionView reloadData]
at key points.
We suspect that the effects of reloadData
are deferred to some point in the future, and there are consequently subtle issues with how this may interact with other method calls like insertItemsAtIndexPaths
, whereas reloadSections
is handled immediately, leaving the collection view in a better state.
We think that we were not seeing this behavior until we started building our app for iOS 8.
Sleep well, my friends!
For me it was the UICollectionViewLayoutAttribute's array. I'm using it in a UICollectionViewLayout
to store item's attribute.
I forgot to empty it in the prepareLayout
method.
So the layoutAttributesForItemAtIndexPath
was returning incorrect values for indexPath, which led to the same crash.
With just a removeAll
on the array at the beginning of prepareLayout, it's working.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With