From a1ee4c19f7a6cbd9899dba82deb5fb3ece669e9c Mon Sep 17 00:00:00 2001 From: Adam Stern Date: Wed, 6 Jun 2018 14:58:23 -0700 Subject: [PATCH] remove duplicate identifiers from IGListBindingSectionController objects Summary: I was building a new `IGListBindingSectionController` subclass and accidentally used two view models with the same ID. Was seeing strange results and realized we're not removing dups or asserting here. Adding a call to `objectsWithDuplicateIdentifiersRemoved` when the view models are first requested. Reviewed By: rnystrom Differential Revision: D8303601 fbshipit-source-id: 42c62adc401feaec2c7dce2a83cfc6533599752b --- CHANGELOG.md | 2 ++ Source/IGListBindingSectionController.m | 3 ++- Tests/IGListBindingSectionControllerTests.m | 30 ++++++++++++++++----- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69bee606..62aac2ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ The changelog for `IGListKit`. Also see the [releases](https://github.com/instag - `[IGListAdapterUpdater performBatchUpdatesWithCollectionViewBlock:]` and `[IGListAdapterUpdater performReloadDataWithCollectionViewBlock:]` clean state and run completion blocks if their `UICollectionView` is nil. [Brandon Darin](https://github.com/jbd1030) (tbd) +- Ensuring view models with duplicate diff identifiers are removed when view models are first requested by `IGListBindingSectionController` [Adam Stern](https://github.com/adamastern) (tbd) + 3.4.0 ----- diff --git a/Source/IGListBindingSectionController.m b/Source/IGListBindingSectionController.m index b769eb82..b831dc50 100644 --- a/Source/IGListBindingSectionController.m +++ b/Source/IGListBindingSectionController.m @@ -112,7 +112,8 @@ typedef NS_ENUM(NSInteger, IGListDiffingSectionState) { self.object = object; if (oldObject == nil) { - self.viewModels = [[self.dataSource sectionController:self viewModelsForObject:object] copy]; + NSArray *viewModels = [self.dataSource sectionController:self viewModelsForObject:object]; + self.viewModels = objectsWithDuplicateIdentifiersRemoved(viewModels); } else { IGAssert([oldObject isEqualToDiffableObject:object], @"Unequal objects %@ and %@ will cause IGListBindingSectionController to reload the entire section", diff --git a/Tests/IGListBindingSectionControllerTests.m b/Tests/IGListBindingSectionControllerTests.m index 65f232f6..c12b9aaa 100644 --- a/Tests/IGListBindingSectionControllerTests.m +++ b/Tests/IGListBindingSectionControllerTests.m @@ -73,6 +73,19 @@ XCTAssertEqualObjects(cell12.textField.text, @"42"); } +- (void)test_withDuplicateDiffIdentifiers_thatDuplicatesAreRemoved { + [self setupWithObjects:@[ + [[IGTestDiffingObject alloc] initWithKey:@1 objects:@[@7, @7]], + ]]; + + XCTAssertEqual([self.collectionView numberOfSections], 1); + XCTAssertEqual([self.collectionView numberOfItemsInSection:0], 1); + + IGTestNumberBindableCell *cell00 = [self cellAtSection:0 item:0]; + + XCTAssertEqualObjects(cell00.textField.text, @"7"); +} + - (void)test_whenUpdating_withAddedModels_thatCellsCorrectAndConfigured { [self setupWithObjects:@[ [[IGTestDiffingObject alloc] initWithKey:@1 objects:@[@7, @"seven"]], @@ -362,21 +375,24 @@ - (void)test_whenUpdating_withMutableArrayObject_thatViewModelsDontMutate { NSArray *objects = @[ - @"foo", - @"bar" - ]; + @"foo", + @"bar" + ]; + NSMutableArray *initObjects = [NSMutableArray arrayWithArray:objects]; - + [self setupWithObjects:@[ [[IGTestDiffingObject alloc] initWithKey:@1 objects:initObjects] ]]; IGTestDiffingSectionController *section = [self.adapter sectionControllerForObject:self.dataSource.objects.firstObject]; - - NSArray *oldModels = [section.viewModels copy]; + + XCTAssertNotEqual(initObjects, section.viewModels); + XCTAssertEqualObjects(initObjects, section.viewModels); + [initObjects removeAllObjects]; - XCTAssertEqual(oldModels, section.viewModels); + XCTAssertNotEqualObjects(initObjects, section.viewModels); } @end