Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prefilling the UICollectionView cell reuse queue

The Problem

I have an app with a single UICollectionView that's stuttering the first time that I scroll it. I've narrowed the source down to the fact that new cells (2) are being created (using initWithFrame:) because there are no cells lying around to be reused. After that initial scroll, the reuse queue isn't empty and cells can be reused and there's no stuttering.

The Hack

So I've been able to workaround the problem with help of a private method in the iOS runtime headers:

- (void)_reuseCell:(id)arg1;

My assumption is that this is where cells are being added back into the reuse queue. The hack to use this undocumented method looks like this:

int prefillCellCount = 10;
NSMutableArray *cells = [[NSMutableArray alloc] initWithCapacity:prefillCellCount];
for (int i=0; i<10prefillCellCount i++) {
    UICollectionViewCell *cell = [self.gridView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
    [cells addObject:cell];
}
for (UICollectionViewCell *cell in cells) {
    [self.gridView _reuseCell:cell];
}

The hack works! There's no stuttering when scrolling.

The Question

I don't think I'll be able to get past the App Store reviewers with this hack. Is there a way to do this without the use of undocumented methods? If not, is my only resort just to obfuscate the hack?

like image 480
Edward Dale Avatar asked Feb 19 '14 10:02

Edward Dale


1 Answers

Is there a way to do this without the use of undocumented methods?

If the problem is simply that it takes a long time to create the cells, then you can simply create a few extras and hold onto them in your view controller until the collection asks for them. Pre-allocate a few cells as you're doing in your code already, calling dequeueReusableCellWithReuseIdentifier: to get the collection to create them for you. Save these in an array in your view controller. Next, in your ...cellForItemAtIndexPath: method, if the array isn't empty remove a cell from the array and use it instead of asking the collection view for a reusable cell.

This should solve your problem by moving the point at which the cells are created without using any undocumented methods.

An alternative approach is to speed up the cell creation process so that you don't have to bother pre-allocating cells. Profile your code to see why your cells take so long to construct. Maybe you can simplify your cell structure by removing unnecessary views?

like image 182
Caleb Avatar answered Nov 06 '22 17:11

Caleb