mirror of
https://github.com/tappollo/IGListKit.git
synced 2026-01-12 22:45:13 +08:00
Add allowsBackgroundReloading Flag to ListAdapterUpdater to Give User Control of Behavior
Summary: Such a powerful framework y'all have made! Game status: changed. - Add a flag to `ListAdapterUpdater` to require it to perform diffing, even when collection view is not in a window. - Ensures delegate can rely on diffing callbacks. - Ensures layout can rely on `prepareForCollectionViewUpdates:`. - Helps with support for AsyncDisplayKit that I'm working on ? - [x] All tests pass. Demo project builds and runs. - [x] I added tests, an experiment, or detailed why my change isn't tested. - [x] I added an entry to the `CHANGELOG.md` for any breaking changes, enhancements, or bug fixes. - [x] I have reviewed the [contributing guide](https://github.com/Instagram/IGListKit/blob/master/.github/CONTRIBUTING.md) Closes https://github.com/Instagram/IGListKit/pull/375 Differential Revision: D4377586 Pulled By: jessesquires fbshipit-source-id: c48467ca5a02ab104d1e83b30430b14b186dbdd2
This commit is contained in:
committed by
Facebook Github Bot
parent
0de9632c0d
commit
71ce9902ca
@@ -19,6 +19,8 @@ This release closes the [2.1.0 milestone](https://github.com/Instagram/IGListKit
|
||||
|
||||
- Added CocoaPods subspec for diffing, `IGListKit/Diffing` and an [installation guide](https://instagram.github.io/IGListKit/installation.html). [Sherlouk](https://github.com/Sherlouk) [(#368)](https://github.com/Instagram/IGListKit/pull/368)
|
||||
|
||||
- Added `allowsBackgroundReloading` flag (default `YES`) to `IGListAdapterUpdater` so users can configure this behavior as needed. [Adlai-Holler](https://github.com/Adlai-Holler) [(#375)](https://github.com/Instagram/IGListKit/pull/375)
|
||||
|
||||
### Fixes
|
||||
|
||||
- Avoid `UICollectionView` crashes when queueing a reload and insert/delete on the same item as well as reloading an item in a section that is animating. [Ryan Nystrom](https://github.com/rnystrom) [(#325)](https://github.com/Instagram/IGListKit/pull/325)
|
||||
|
||||
@@ -37,6 +37,17 @@ IGLK_SUBCLASSING_RESTRICTED
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL movesAsDeletesInserts;
|
||||
|
||||
/**
|
||||
A flag indicating whether this updater should skip diffing and simply call
|
||||
`reloadData` for updates when the collection view is not in a window. The default value is `YES`.
|
||||
|
||||
@note This will result in better performance, but will not generate the same delegate
|
||||
callbacks. If using a custom layout, it will not receive `prepareForCollectionViewUpdates:`.
|
||||
|
||||
@warning On iOS < 8.3, this behavior is unsupported and will always be treated as `NO`.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL allowsBackgroundReloading;
|
||||
|
||||
/**
|
||||
A bitmask of experiments to conduct on the updater.
|
||||
*/
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
|
||||
#import "UICollectionView+IGListBatchUpdateData.h"
|
||||
|
||||
@implementation IGListAdapterUpdater {
|
||||
BOOL _canBackgroundReload;
|
||||
}
|
||||
@implementation IGListAdapterUpdater
|
||||
|
||||
- (instancetype)init {
|
||||
IGAssertMainThread();
|
||||
@@ -36,7 +34,7 @@
|
||||
_insertIndexPaths = [[NSMutableSet alloc] init];
|
||||
_reloadIndexPaths = [[NSMutableSet alloc] init];
|
||||
|
||||
_canBackgroundReload = [[[UIDevice currentDevice] systemVersion] compare:@"8.3" options:NSNumericSearch] != NSOrderedAscending;
|
||||
_allowsBackgroundReloading = YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -155,7 +153,8 @@ static NSArray *objectsWithDuplicateIdentifiersRemoved(NSArray<id<IGListDiffable
|
||||
|
||||
// if the collection view isn't in a visible window, skip diffing and batch updating. execute all transition blocks,
|
||||
// reload data, execute completion blocks, and get outta here
|
||||
if (_canBackgroundReload && collectionView.window == nil) {
|
||||
const BOOL iOS83OrLater = (NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_8_3);
|
||||
if (iOS83OrLater && self.allowsBackgroundReloading && collectionView.window == nil) {
|
||||
[self beginPerformBatchUpdatestoObjects:toObjects];
|
||||
executeUpdateBlocks();
|
||||
[self cleanupUpdateBlockState];
|
||||
|
||||
@@ -459,4 +459,50 @@
|
||||
XCTAssertEqual([collectionView numberOfItemsInSection:1], 4);
|
||||
}
|
||||
|
||||
- (void)test_whenCollectionViewNotInWindow_andBackgroundReloadFlag_isSetNO_diffHappens {
|
||||
self.updater.allowsBackgroundReloading = NO;
|
||||
[self.collectionView removeFromSuperview];
|
||||
|
||||
id mockDelegate = [OCMockObject niceMockForProtocol:@protocol(IGListAdapterUpdaterDelegate)];
|
||||
self.updater.delegate = mockDelegate;
|
||||
[mockDelegate setExpectationOrderMatters:YES];
|
||||
[[mockDelegate expect] listAdapterUpdater:self.updater willPerformBatchUpdatesWithCollectionView:self.collectionView];
|
||||
[[mockDelegate expect] listAdapterUpdater:self.updater didPerformBatchUpdates:OCMOCK_ANY withCollectionView:self.collectionView];
|
||||
|
||||
XCTestExpectation *expectation = genExpectation;
|
||||
NSArray *to = @[
|
||||
[IGSectionObject sectionWithObjects:@[]]
|
||||
];
|
||||
[self.updater performUpdateWithCollectionView:self.collectionView fromObjects:self.dataSource.sections toObjects:to animated:NO objectTransitionBlock:self.updateBlock completion:^(BOOL finished) {
|
||||
[expectation fulfill];
|
||||
}];
|
||||
waitExpectation;
|
||||
[mockDelegate verify];
|
||||
}
|
||||
|
||||
- (void)test_whenCollectionViewNotInWindow_andBackgroundReloadFlag_isDefaultYES_diffDoesNotHappen {
|
||||
[self.collectionView removeFromSuperview];
|
||||
|
||||
id mockDelegate = [OCMockObject niceMockForProtocol:@protocol(IGListAdapterUpdaterDelegate)];
|
||||
self.updater.delegate = mockDelegate;
|
||||
|
||||
// NOTE: The current behavior in this case is for the adapter updater
|
||||
// simply not to call any delegate methods at all. This may change
|
||||
// in the future, but we configure the mock delegate to allow any call
|
||||
// except the batch updates calls.
|
||||
|
||||
[[mockDelegate reject] listAdapterUpdater:self.updater willPerformBatchUpdatesWithCollectionView:self.collectionView];
|
||||
[[mockDelegate reject] listAdapterUpdater:self.updater didPerformBatchUpdates:OCMOCK_ANY withCollectionView:self.collectionView];
|
||||
|
||||
XCTestExpectation *expectation = genExpectation;
|
||||
NSArray *to = @[
|
||||
[IGSectionObject sectionWithObjects:@[]]
|
||||
];
|
||||
[self.updater performUpdateWithCollectionView:self.collectionView fromObjects:self.dataSource.sections toObjects:to animated:NO objectTransitionBlock:self.updateBlock completion:^(BOOL finished) {
|
||||
[expectation fulfill];
|
||||
}];
|
||||
waitExpectation;
|
||||
[mockDelegate verify];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user