Working with UICollectionView
This guide provides details on how to work with UICollectionView
and IGListKit
.
Background
Early versions of IGListKit
(2.x and prior) shipped with a subclass of UICollectionView
called IGListCollectionView
. The class contained no special functionality and was merely used to enforce compile-time restrictions to prevent users from calling certain methods directly on UICollectionView
. Beginning with 3.0, IGListCollectionView
was removed for a number of reasons.
For further discussion see #240 and #409.
Methods to avoid
One of the primary purposes of IGListKit
is to perform optimal batch updates for UICollectionView
. Thus, clients should never call any APIs on UICollectionView
that involved reloading, inserting, deleting, or otherwise updating cells and index paths. Instead, use the APIs provided by IGListAdapter
. You should also avoid setting the delegate
and dataSource
of the collection view, as this is also the responsibility of IGListAdapter
.
Avoid calling the following methods:
- (void)performBatchUpdates:(void (^)(void))updates
completion:(void (^)(BOOL))completion;
- (void)reloadData;
- (void)reloadSections:(NSIndexSet *)sections;
- (void)insertSections:(NSIndexSet *)sections;
- (void)deleteSections:(NSIndexSet *)sections;
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection;
- (void)insertItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
- (void)reloadItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
- (void)deleteItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath;
- (void)setDelegate:(id<UICollectionViewDelegate>)delegate;
- (void)setDataSource:(id<UICollectionViewDataSource>)dataSource;
- (void)setBackgroundView:(UIView *)backgroundView;
Performance
In iOS 10, a new cell prefetching API was introduced. At Instagram, enabling this feature substantially degraded scrolling performance. We recommend setting isPrefetchingEnabled
to NO
(false
in Swift). Note that the default value is true
.
You can set this globally using UIAppearance
:
if ([[UICollectionView class] instancesRespondToSelector:@selector(setPrefetchingEnabled:)]) {
[[UICollectionView appearance] setPrefetchingEnabled:NO];
}
if #available(iOS 10, *) {
UICollectionView.appearance().isPrefetchingEnabled = false
}