Lucas van Dongen
Lucas van Dongen

Reputation: 9858

UICollectionView stuck in infinite loop in iOS 7 since I started to use the iOS 8 SDK

So I've been updating an app I'm maintaining for iOS 8 but I'm experiencing problems in iOS 7 that I did not have when I was using the iOS 7 SDK.

If I don't touch the code at all it ends op in a loop (90% CPU without stopping) when the code calls into layoutSubviews. It changes a bit when I play and pause but validateLayoutInRect: always seems to be there.

enter image description here

When I change layoutSubviews in layoutIfNeeded it passes but gets stuck in a very similar way after calling the following line:

[collectionView layoutAttributesForItemAtIndexPath:indexPath];

enter image description here

update: enabling and setting auto layouts on the parent view makes it pass layoutSubviews as well, that part of the problem might have to do with auto layouts in the xibs but not on the hosting view controller

To me it seems that it gets stuck calculating the size, changing something that triggers a recalculation and so on. It's weird that it doesn't happen with iOS 7 SDK -> iOS 7 phone and iOS 8 SDK -> iOS 8 phone nor iOS 7 SDK -> iOS 8 phone.

I tried to put NSLog messages at various points where it could surface in my code again but nothing is getting called in a loop. The Collection View is filled by reusing .xib files. I would like to rebuild it to use just storyboards but it's a very complex screen and at this point I am actually not sure if this really is my bug or a bug in the SDK.

Upvotes: 3

Views: 2315

Answers (1)

Lucas van Dongen
Lucas van Dongen

Reputation: 9858

When I compiled with the iOS 8.1 SDK in Xcode 6.1 things already got a lot better. But there was still one screen crashing. Eventually I figured out some cells ended up being MAXFLOAT high and I needed to add a sanity check before applying that height:

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout *)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    Class class = [[self dataSource] cellClassForIndexPath:indexPath];
    NSString *classString = NSStringFromClass(class);
    UICollectionViewCell *cell = [self sizingCells][classString];

    if (cell == nil)
    {
        cell = [class loadInstanceFromNib];
        [self sizingCells][classString] = cell;
    }

    [[self dataSource] configureCell:cell forIndexPath:indexPath excludeKeys:@[@"imageURL", @"image"]];

    CGSize fittingSize = CGSizeMake([collectionView frameSizeWidth], MAXFLOAT);
    CGSize size = [cell systemLayoutSizeFittingSize:fittingSize];

    if (size.height > 10000) { // Needed for iOS 8 SDK on iOS 7 device bug AMA-827
        size.height = cell.frame.size.height; // Ridiculous size detected, whipping
    }

    return CGSizeMake([collectionView frameSizeWidth], size.height);
}

I arbitrarily decided that anything above 10000 probably wasn't what I intended and put in the cell frame height instead. Works in this case everywhere I need it!

Most of it isn't my code, don't slap me for the old fashioned style of CGRects everywhere ;)


I noticed it got downvoted twice. Please tell me what is wrong with this working answer.

Upvotes: 2

Related Questions