Reputation: 3464
I'm trying to imitate UITableView layout using UICollectionView.
layout.itemSize = CGSizeMake(CGRectGetWidth(self.view.bounds), 44.0f);
I register the reusable cell class.
[self.collectionView registerClass:[SampleCell class]
forCellWithReuseIdentifier:NSStringFromClass([SampleCell class])];
Note: SampleClass
is just a subclass of UICollectionViewCell
which contains nothing.
And conformed to the data source:
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 28;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([SampleCell class])
forIndexPath:indexPath];
return cell;
}
I found that the SampleCell
is not reused. To validate it, we can simply log the number of subviews in the UICollectionView
.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog(@"number of subviews in collection view is: %li", (long)self.collectionView.subviews.count);
}
And after scrolling, I got this log:
number of subviews in collection view is: 30
number of subviews in collection view is: 30
number of subviews in collection view is: 30
number of subviews in collection view is: 30
Notice that there are 30 subviews (2 of those are the scrollview indicator).
That means that all of the 28 items are displayed without the invisible cells removed from superview. Why does this happen?
To make it easier for you, I made a sample project available on Github. https://github.com/edwardanthony/UICollectionViewBug
I also checked the memory allocation using the memory graph hierarchy debugger and it's allocated 28 times.
Upvotes: 2
Views: 1230
Reputation: 4323
I does work, it's just keeping a little more in memory due to more aggressive caching. If you try changing the number of items from 28 to 100 you will see that it stays at 33 subviews when you scroll.
Try adding the following code to your SampleCell
class and you will see it gets called, but maybe not quite as you expect.
- (void)prepareForReuse {
[super prepareForReuse];
NSLog(@"prepareForReuse called");
}
UICollectionView
has a more advanced caching scheme than UITableView
(or at least as it used to have), which is the reason you see what you do. According to docs it says Cell prefetching is enabled by default:
UICollectionView provides two prefetching techniques you can use to improve responsiveness:
Cell prefetching prepares cells in advance of the time they are required. When a collection view requires a large number of cells simultaneously—for example, a new row of cells in grid layout—the cells are requested earlier than the time required for display. Cell rendering is therefore spread across multiple layout passes, resulting in a smoother scrolling experience. Cell prefetching is enabled by default.
Data prefetching provides a mechanism whereby you are notified of the data requirements of a collection view in advance of the requests for cells. This is useful if the content of your cells relies on an expensive data loading process, such as a network request. Assign an object that conforms to the UICollectionViewDataSourcePrefetching protocol to the prefetchDataSource property to receive notifications of when to prefetch data for cells.
You can turn off cell prefetching by adding this line to setupCollectionView
function in your sample:
self.collectionView.prefetchingEnabled = NO;
Doing so will make your sample work as you expected. The subview count will drop to 18 in my case.
Upvotes: 4
Reputation: 578
I suspect that counting subviews does not reflect cell reuse. It could be that subviews contains more than one reference to the same cell. To count the number of cells used, you could log how many times the UICollectionViewCell subclass gets initialised. Just override it's init method and put a print statement in there.
One other thing to note (sorry if it's aleady obvious), if all cells are visible on screen no reuse will occur. Cell reuse occurs when cells go off screen during scrolling.
Upvotes: 1