Calling setCollectionViewLayout:animated does not reload UICollectionView

-setCollectionViewLayout: or -setCollectionViewLayout:animated: won't cause your UICollectionView reload its data.

  • If you want to change your cell style or update the data, call [self.collectionView reloadData] and UICollectionViewDataSource protocol methods will be called.

  • If you want to change your UICollectionView layout to another, call -setCollectionViewLayout:. Or if you want to update your UICollectionView layout, just call [self.collectionView.collectionViewLayout invalidateLayout].

Cell layout and data are two different things in UICollectionView.

Update
you should discard all the stale data, probably by -reloadData. And calculate the new frames for every cell in your UICollectionViewLayout subclasses. Override - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath and - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect.
You decide the new contentOffset. For instance, you could keep the indexPath of some visible cell and decide to scroll to that indexPath or setContentOffset: to the frame.origin of the new cell at the same indexPath after your layout changed.

  • And I find this answer may give you help.
  • Also check the awesome video WWDC 2012 Advanced Collection Views and Building Custom Layouts

Simply call reloadData before you switch your layout (the performBatchUpdates call is not mandatory):

[self.collectionView reloadData];
[self.collectionView.collectionViewLayout invalidateLayout];
[self.collectionView setCollectionViewLayout:yourLayout animated:YES];

In Swift:

self.collectionView?.reloadData()
self.collectionView?.collectionViewLayout.invalidateLayout()
self.collectionView?.setCollectionViewLayout(yourLayout, animated: true)