I have some data that is fetched in another thread that updates a UICollectionView's header. However, I've not found an efficient way of reloading a supplementary view such as a header or footer.
I can call collectionView reloadSections:
, but this reloads the entire section which is unnecessary. collectionView reloadItemsAtIndexPaths:
only seems to target cells (not supplementary views). And calling setNeedsDisplay
on the header itself doesn't appear to work either. Am I missing something?
Here's what I did to update only the section headers that are currently loaded in memory:
NSMapTable
. When you create a header, add the header as the weakly held key, with the indexPath object. If we reuse the header we'll update the indexPath.NSMapTable
as needed.I just ran into the same problem, and I ended up looking up the view using its tag to edit a label:
Like you said it is unnecessary to reload an entire section, which cancels out any animation on cells as well. My solution isn't ideal, but it's easy enough.
This question is very old but a simple way to do it is to just set a delay that covers the time your view is animating and disabling the animation while you update the view...usually a delete or insert takes about .35 seconds so just do:
You can also use (the lazy way)
More complex would be to provide a context
You can then make a or configure the context yourself to inform about what should be updated see: UICollectionViewLayoutInvalidationContext
It has a function in there that you can override:
Another option is (if you have already loaded the correct header/footer/supplementary view) and you only want to update the view with the new data than you can use one of the following functions to retrieve it:
supplementaryView(forElementKind:at:) // get specific one
visibleSupplementaryViews(ofKind:) // all visible ones
Same goes for visible cells with
visibleCells
. The advantage of just getting the view and not reloading a view entirely is that the cells retains it state. This is espically nice with table view cells when they use swipe to delete/edit/etc since that state is lost after reloading the cell.If you feel fanatic you can of course also write some extensions to retrieve only cells/supplementary views of a given kind using generics
this assumes that you have a function that registers/dequeues views in example with their class name. I made a post about this here
Here are two ways you could do it.
1. Create a mutable model to back the data that will eventually be available. Use KVO in inherited class of UICollectionReusableView to observe the changes and update the header view with the new data as it comes available.
then implement listener method in header view
2. add notification listener to the view and post a notification when the data has successfully come available. Downside is that this is application wide and not a clean design.
My problem arose when frame sizes for the supplementary views changed upon invalidating the layout. It appeared that the supplementary views were not refreshing. It turns out they were, but I was building the
UICollectionReusableView
objects programmatically, and I was not removing the oldUILabel
subviews. So when the collection view dequeued each header view, the UILabels would pile up, causing erratic appearance.The solution was to build each UICollectionReusableView completely inside the
viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
method, starting by a) removing all subviews from the dequeued cell, then b) getting the frame size from the item's layout attributes to allow adding the new subviews.