Make sure collection have unique ListDiffable objects on initial data…

Summary:
… source setup too

Issue fixed: #815

- [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/993

Reviewed By: manicakes

Differential Revision: D6388270

Pulled By: rnystrom

fbshipit-source-id: e5e7e047bad5f21b81b562ebd586f7f5036325ff
This commit is contained in:
yemodin 2017-11-21 13:03:27 -08:00 committed by Facebook Github Bot
parent a0cf76c757
commit c7d4dc29a8
5 changed files with 12 additions and 10 deletions

View file

@ -19,6 +19,8 @@ The changelog for `IGListKit`. Also see the [releases](https://github.com/instag
### Fixes
- Duplicate objects for initial data source setup filtered out. [Mikhail Vashlyaev](https://github.com/yemodin) [(#993](https://github.com/Instagram/IGListKit/pull/993)
- Weakly reference the `UICollectionView` in coalescence so that it can be released if the rest of system is destroyed. [Ryan Nystrom](https://github.com/rnystrom) [(#tbd)](https://github.com/Instagram/IGListKit/pull/tbd)
- Fix bug with `-[IGListAdapter scrollToObject:supplementaryKinds:scrollDirection:scrollPosition:animated:]` where the content inset of the collection view was incorrectly being applied to the final offset. [Ryan Nystrom](https://github.com/rnystrom) [(#tbd)](https://github.com/Instagram/IGListKit/pull/tbd)

View file

@ -24,7 +24,7 @@ static NSArray *objectsWithDuplicateIdentifiersRemoved(NSArray<id<IGListDiffable
[identifiers addObject:diffIdentifier];
[uniqueObjects addObject:object];
} else {
IGLKLog(@"WARNING: Object %@ already appeared in objects array", object);
IGLKLog(@"WARNING: Diff identifier %@ for object %@ already appeared in objects array", diffIdentifier, object);
}
}
return uniqueObjects;

View file

@ -15,6 +15,7 @@
#import "IGListSectionControllerInternal.h"
#import "IGListDebugger.h"
#import "IGListArrayUtilsInternal.h"
@implementation IGListAdapter {
NSMapTable<UICollectionReusableView *, IGListSectionController *> *_viewSectionControllerMap;
@ -143,7 +144,8 @@
- (void)updateAfterPublicSettingsChange {
id<IGListAdapterDataSource> dataSource = _dataSource;
if (_collectionView != nil && dataSource != nil) {
[self updateObjects:[[dataSource objectsForListAdapter:self] copy] dataSource:dataSource];
NSArray *uniqueObjects = objectsWithDuplicateIdentifiersRemoved([dataSource objectsForListAdapter:self]);
[self updateObjects:uniqueObjects dataSource:dataSource];
}
}
@ -359,13 +361,13 @@
return;
}
NSArray *newItems = [[dataSource objectsForListAdapter:self] copy];
NSArray *uniqueObjects = objectsWithDuplicateIdentifiersRemoved([dataSource objectsForListAdapter:self]);
__weak __typeof__(self) weakSelf = self;
[self.updater reloadDataWithCollectionView:collectionView reloadUpdateBlock:^{
// purge all section controllers from the item map so that they are regenerated
[weakSelf.sectionMap reset];
[weakSelf updateObjects:newItems dataSource:dataSource];
[weakSelf updateObjects:uniqueObjects dataSource:dataSource];
} completion:^(BOOL finished) {
[weakSelf notifyDidUpdate:IGListAdapterUpdateTypeReloadData animated:NO];
if (completion) {
@ -575,11 +577,8 @@
IGParameterAssert(dataSource != nil);
#if DEBUG
NSCountedSet *identifiersSet = [NSCountedSet new];
for (id object in objects) {
[identifiersSet addObject:[object diffIdentifier]];
IGAssert([object isEqualToDiffableObject:object], @"Object instance %@ not equal to itself. This will break infra map tables.", object);
IGAssert([identifiersSet countForObject:[object diffIdentifier]] <= 1, @"Diff identifier %@ for object %@ occurs more than once. Identifiers must be unique!", [object diffIdentifier], object);
}
#endif

View file

@ -1527,9 +1527,10 @@
XCTAssertEqual(collectionView1.dataSource, adapter2);
}
- (void)test_whenPassingNonUniqueIdentifiers_adapterShouldAssert {
- (void)test_whenPassingNonUniqueIdentifiers_adapterReloadShouldSkipDuplicates {
self.dataSource.objects = @[@0, @1, @2, @0];
XCTAssertThrows([self.adapter reloadDataWithCompletion:nil]);
[self.adapter reloadDataWithCompletion:nil];
XCTAssertEqual(self.adapter.objects.count, 3);
}
- (void)test_whenPrefetchingEnabled_thatSetterDisables {

View file

@ -45,7 +45,7 @@
adapter3.collectionView = collectionView;
NSArray *descriptions = [IGListDebugger adapterDescriptions];
XCTAssertEqual(descriptions.count, 4);
XCTAssertEqual(descriptions.count, 3);
}
@end