Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reload UICollectionView header or footer?

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?

like image 543
akaru Avatar asked Dec 12 '12 00:12

akaru


2 Answers

You can also use (the lazy way)

collectionView.collectionViewLayout.invalidateLayout() // swift  [[_collectionView collectionViewLayout] invalidateLayout] // objc 

More complex would be to provide a context

collectionView.collectionViewLayout.invalidateLayout(with: context) // swift  [[_collectionView collectionViewLayout] invalidateLayoutWithContext:context] // objc 

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:

invalidateSupplementaryElements(ofKind:at:) // swift 

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

if let view = supplementaryView(forType: MySupplementaryView.self, at: indexPath) {     configure(view, at indexPath) } 

this assumes that you have a function that registers/dequeues views in example with their class name. I made a post about this here

like image 57
Saren Inden Avatar answered Sep 22 '22 07:09

Saren Inden


I just ran into the same problem, and I ended up looking up the view using its tag to edit a label:

UICollectionReusableView *footer = (UICollectionReusableView*)[self.collectionView viewWithTag:999]; UILabel *footerLabel = (UILabel*)[footer viewWithTag:100]; 

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.

like image 34
Bob Vork Avatar answered Sep 23 '22 07:09

Bob Vork