Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vertically scrolling UICollectionView with self-sizing cells only displays half the cells

I've set up a UICollectionView (with the default flow layout, and vertical scrolling) with custom cells that load from a xib. The cells contain a couple of elements (a UILabel and a UIView) with constraints on them. I've set up the constraints such that the cell height grows as the label text height increases using the new UICollectionViewFlowLayout property that's available in iOS8, estimatedItemSize:

layout.estimatedItemSize = CGSizeMake(self.collectionView.frame.width, 100)

Everything works like a charm except there's one big problem: the UICollectionView loads only half the items as returned by the numberOfItemsInSection method. So, when the method returns, say, 10, my UICollectionView only displays 5 cells (but displays and lays them out perfectly).

Some relevant findings from my debugging attempts:

  • I've been able to force the loading of the remaining items by calling invalidateLayout or changing the number of sections from 1 to 2. But those are just debugging hacks.
  • Separately, everything works like a charm when I replace estimatedItemSize with the itemSize property, i.e. hard-coding the item size. But that defeats the self-sizing functionality I'd like to implement.

I'm assuming there's something wrong with how I'm thinking about self-sized cells. Specifically, I wonder if the problem has something to do with constraints.

I'd appreciate any help here.

like image 755
rainypixels Avatar asked Aug 29 '14 18:08

rainypixels


2 Answers

I believe this is due to a bug in iOS8 which still exists as of iOS8.3.

Flow layout collection views with self-sizing cells will fail to display some of their content if the estimatedItemSize is too small. This is despite the fact that according to the the API docs the only requirement on the estimatedItemSize is that it be non-zero to trigger the self-sizing behavior.

Only Apple is in a position to fix this. I think the best workaround in the mean time is to put an inflated value into estimatedItemSize`.

This repo demonstrates the issue: https://github.com/algal/SelfSizingCellsDemo. (I've filed a radar at rdar://18078598.)

like image 88
algal Avatar answered Nov 16 '22 01:11

algal


The obvious non-hacky solution is to implement

flowLayout.collectionView(layout:sizeForItemAtIndexPath:)

but of course that is more code than you presumably have hoped for.

I would suggest you try two more things:

  1. Try to experiment with more plausible estimated sizes. Also try the default value, CGSizeZero.
  2. Check what happens in preferredlLayoutAttributesFittingAttributes() by examining the layoutAttributes parameter. Maybe you find a clue to why the other cells are "crowded out".
like image 41
Mundi Avatar answered Nov 16 '22 02:11

Mundi