From ee4f3c95c6861f2b5b6b958e549e1842a740ae61 Mon Sep 17 00:00:00 2001 From: Ryan Nystrom Date: Sat, 22 Apr 2017 12:08:14 -0700 Subject: [PATCH] Balance reload delete and insert calls Summary: In https://github.com/Instagram/IGListKit/commit/073fc073e03c09abfeca022173e9d063d513e137 we deduped delete calls, but since we convert reloads into delete+insert when only deduping deletes, we end up with unbalanced delete+insert calls. Unit test added reproduced a crash we see internally. Fix passes the test. Not adding a changelog entry since this is a new regression fixed between releases. #trivial Issue fixed: t17539856 - [x] All tests pass. Demo project builds and runs. - [x] I added tests, an experiment, or detailed why my change isn't tested. Closes https://github.com/Instagram/IGListKit/pull/687 Differential Revision: D4933545 Pulled By: rnystrom fbshipit-source-id: d38a900a99b1aa796dd654ddedb42e3cb4ef4378 --- Source/IGListAdapterUpdater.m | 8 ++++++-- Tests/IGListAdapterE2ETests.m | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/Source/IGListAdapterUpdater.m b/Source/IGListAdapterUpdater.m index 75003eec..33b24548 100644 --- a/Source/IGListAdapterUpdater.m +++ b/Source/IGListAdapterUpdater.m @@ -280,12 +280,16 @@ void convertReloadToDeleteInsert(NSMutableIndexSet *reloads, NSMutableArray *itemMoves = batchUpdates.itemMoves; NSSet *uniqueDeletes = [NSSet setWithArray:itemDeletes]; + NSMutableSet *reloadDeletePaths = [NSMutableSet new]; + NSMutableSet *reloadInsertPaths = [NSMutableSet new]; for (IGListReloadIndexPath *reload in batchUpdates.itemReloads) { if (![uniqueDeletes containsObject:reload.fromIndexPath]) { - [itemDeletes addObject:reload.fromIndexPath]; - [itemInserts addObject:reload.toIndexPath]; + [reloadDeletePaths addObject:reload.fromIndexPath]; + [reloadInsertPaths addObject:reload.toIndexPath]; } } + [itemDeletes addObjectsFromArray:[reloadDeletePaths allObjects]]; + [itemInserts addObjectsFromArray:[reloadInsertPaths allObjects]]; IGListBatchUpdateData *updateData = [[IGListBatchUpdateData alloc] initWithInsertSections:inserts deleteSections:deletes diff --git a/Tests/IGListAdapterE2ETests.m b/Tests/IGListAdapterE2ETests.m index 636779e6..3183bc84 100644 --- a/Tests/IGListAdapterE2ETests.m +++ b/Tests/IGListAdapterE2ETests.m @@ -1460,5 +1460,24 @@ [self waitForExpectationsWithTimeout:30 handler:nil]; } +- (void)test_whenReloadingSameItemTwice_thatDeletesAndInsertsAreBalanced { + [self setupWithObjects:@[ + genTestObject(@1, @4), + ]]; + + IGTestObject *object = self.dataSource.objects[0]; + IGListSectionController *sectionController = [self.adapter sectionControllerForObject:object]; + + XCTestExpectation *expectation = genExpectation; + [sectionController.collectionContext performBatchAnimated:YES updates:^(id batchContext) { + [batchContext reloadInSectionController:sectionController atIndexes:[NSIndexSet indexSetWithIndex:0]]; + [batchContext reloadInSectionController:sectionController atIndexes:[NSIndexSet indexSetWithIndex:0]]; + } completion:^(BOOL finished2) { + XCTAssertEqual([self.collectionView numberOfSections], 1); + XCTAssertEqual([self.collectionView numberOfItemsInSection:0], 4); + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:30 handler:nil]; +} @end