Closer to understanding the crash
This is a 1:1 replacement of UITVC without pissing Apple off.
First, this is where your callback gets used.
// if delegate implements size delegate, query it for all items
if (implementsSizeDelegate) {
for (NSInteger item = 0; item < numberOfItems; item++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:item inSection:(NSInteger)section];
CGSize itemSize = implementsSizeDelegate ? [flowDataSource collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath] : self.itemSize;
PSTGridLayoutItem *layoutItem = [layoutSection addItem];
layoutItem.itemFrame = (CGRect){.size=itemSize};
}
https://github.com/steipete/PSTCollectionView/blob/master/PSTCollectionView/PSTCollectionView.m
Look at attributes assignment and the very last line...
- (id)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath {
// de-queue cell (if available)
NSMutableArray *reusableCells = _cellReuseQueues[identifier];
PSTCollectionViewCell *cell = [reusableCells lastObject];
PSTCollectionViewLayoutAttributes *attributes = [self.collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath];
// ... IMPL ...
[cell applyLayoutAttributes:attributes];
return cell;
}
There is much code to go through but there is at least one path where you can fall into infinite recursion...
Edit
From the link I posted below...
Since collectionView:layout:sizeForItemAtIndexPath: is called before
cellForItemAtIndexPath:, so we need to initialize a cell and let
system use auto layout to calculate height for us. To avoid memory
leak, we use a dictionary to cache the cells that are off screen (not
shown on screen)
In collectionView:layout:sizeForItemAtIndexPath:, first create or retrieve a cell
var cell: MyCollectionViewCell? = self.offscreenCells[reuseIdentifier] as? MyCollectionViewCell
if cell == nil {
cell = NSBundle.mainBundle().loadNibNamed("MyCollectionViewCell", owner: self, options: nil)[0] as? MyCollectionViewCell
self.offscreenCells[reuseIdentifier] = cell
}
Once a cell is initialized, its size is determined by size in xib file, thus, we need configure texts in cell and layoutSubviews, this will let system recalculate the size of cell
// Config cell and let system determine size
cell!.configCell(titleData[indexPath.item], content: contentData[indexPath.item], titleFont: fontArray[indexPath.item] as String, contentFont: fontArray[indexPath.item] as String)
// Cell's size is determined in nib file, need to set it's width (in this case), and inside, use this cell's width to set label's preferredMaxLayoutWidth, thus, height can be determined, this size will be returned for real cell initialization
cell!.bounds = CGRectMake(0, 0, targetWidth, cell!.bounds.height)
cell!.contentView.bounds = cell!.bounds
// Layout subviews, this will let labels on this cell to set preferredMaxLayoutWidth
cell!.setNeedsLayout()
cell!.layoutIfNeeded()
Once cell is updated, call var size =
cell!.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
to get the size for this cell.
In cellForItemAtIndexPath:, cell also need configured and layout its
subviews
Orig
Well, it doesn't crash when calling the method you named (half of it), it crashes when calling
dequeueReusableCellWithReuseIdentifier(MessageCellIdentifier,
forIndexPath: indexPath) as! MessageCell
The problem I see with it is that you are trying to call a method that needs the method you are calling it from to give you an answer. It should produce a stack overflow.
I'm not saying it's impossible but you aren't overriding enough or the right methods I believe.
Check out the https://github.com/honghaoz/Dynamic-Collection-View-Cell-With-Auto-Layout-Demo/blob/master/README.md for an example of what you want, and/or post more code.