cnoon / CollectionViewAnimations

Sample project demonstrating how to expand / collapse collection view cells using custom animation blocks.
MIT License
257 stars 22 forks source link

Peek & Pop results in crash, fails to validateLayoutInRect #6

Open Laptopmini opened 6 years ago

Laptopmini commented 6 years ago

First I wanted to say @cnoon, what a great repo.. Everything was well explained, and really easy to integrate. Honestly, congrats.

However, I think I discovered a bug in relation to Peek & Pop, which is new since you've written this. I've been hunting it down the cause for quite a while, running the google machine like crazy to no avail.

At this point, I'm kind of at a loss. I was hoping you (or someone) might have some insight on what to investigate.

Bug Context

When implementing UIViewControllerPreviewingDelegate in my UICollectionViewController, you are required to implement the following:

func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController?

Which requires you to return the UIViewController representing the preview, or nil.

Exception

The issue however is that when a non-nil value is returned, it results in an assertion failure.

Assertion failure in -[UICollectionViewData validateLayoutInRect:]

Which itself raises the exception:

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}'

Investigation

So because the problem here seems to be that the collectionView seems to be unable to validate the layout, I have to figure out where it might be getting bad layout attributes.

At first I tried to "overly" invalidate the layout in bunch of places, to force it to always have the latest "prepared" attributes. Did not work.

I then tried disabling some of the overwritten methods in my UICollectionViewLayout to have it revert back to some default behavior. I have another UICollectionView with a custom layout where peak and pop works great (it does not have expandable cells), so I tried replicating its setup of overwritten methods. (such as removing finalLayoutAttributesForDisappearingItem) Did not work.

I tried a lot of various solutions found on SO related to the exception, but none worked; most where for people who simply had "outdated" layouts that needed invalidation, and their crashes occurred during scrolling. I couldn't find a solution that worked, nor one about Peek & Pop particularly.

I tried having some of the UICollectionViewLayout return more data than needed, such as layoutAttributesForElements(in rect: CGRect) ignoring the rect and returning the whole cache, or having shouldInvalidateLayout(forBoundsChange newBounds: CGRect) always return true. Did not work.

Conclusion

Can't manage to have it Peek without raising an exception.

Sorry for the long issue, and I realize you have long left this repo behind, but I'm pretty desperate for a solution or any leads. I'd hate to have to give up on Peek & Pop.

Thanks

Laptopmini commented 6 years ago

Followup (last updated: 11/17/2017 @ 11:07pm (UTC))

I tried placing a debug statement in all methods of the layout, to see what gets called when doing a Peek & Pop. None of them seem to be called.

So either I am missing an implementation of a method in the layout which UICollectionViewData.validateLayoutInRect() relies on, or its getting its data from somewhere else.