Overriding invalidateLayout

I have a custom UICollectionViewLayout subclass, and I am trying to understand what is the proper way to handle overriding invalidateLayout() and invalidateLayout(with: UICollectionViewLayoutInvalidationContext).


At first, I thought it was sufficient to only override invalidateLayout(with: UICollectionViewLayoutInvalidationContext), and use the context to figure out what needs to be discarded from my cached layout data. This works unless I call invaliateLayout() myself, with the intention of discarding all the layout data. Calling invalidateLayout() eventually calls invalidateLayout(with: UICollectionViewLayoutInvalidationContext), but as far as I can tell, the context passed in has nothing marked for invalidation. I expected "invalidateEverything" to be true, like it is when reloadData is called, but it's not. So there's nothing in the context I can use to identify that the call originated from a call to invalidateLayout() that would let me know I should discard all the cached layoutData.


So then I figured I should also override invalidateLayout(), and discard everything there. But then I discovered that every time any kind of invalidation occurs, whether it's from batch updates, bounds change, or anything else, invalidateLayout() always gets called, and it is in super.invalidateLayout() that invalidateLayout(with: UICollectionViewLayoutInvalidationContext) eventually gets called. So if I discard all cached layoutData there, it becomes pointless to override invalidateLayout(with: UICollectionViewLayoutInvalidationContext). I'll end up invalidating everything all the time, and lose the added efficiency of using contexts.


Apparently UICollectionViewLayout stores a context somewhere internally, so that when invalidateLayout() is called, it can grab that saved context and pass it into invalidateLayout(with: UICollectionViewLayoutInvalidationContext). Ideally, I should be able to specify the context that is passed in when invalidateLayout() is called manually. I know I can provide a custom subclass of UICollectionViewLayoutInvalidationContext, but I don't think that will let me distinguish a manual invalidation from the internal ones that occur during batch updates.


The documentation doesn't really address this. It recommends discarding all cached data in invalidateLayout(), but doing so actually breaks invalidation with contexts because invalidateLayout() is always called right before invalidateLayout(with: UICollectionViewLayoutInvalidationContext). Am I wrong in thinking that manually calling invalidateLayout() is supposed to mean, "invalidate everything and rebuild the whole layout"? Or is there actually a way for me to control what instance of a context is created when invalidateLayout() is manually called, so I can know that it was called manually and I should discard everything?