diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f4113e4..03c8efb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ The changelog for `IGListKit`. Also see the [releases](https://github.com/instag - 5x improvement to diffing performance when result is only inserts or deletes. [Ryan Nystrom](https://github.com/rnystrom) [(tbd)](tbd) ### Fixes +- Copy objects when retrieving from datasource to prevent modification of models in binding section controller. [Kashish Goel](https://github.com/kashishgoel) [(#1109)](https://github.com/Instagram/IGListKit/pull/1109) 3.2.0 ----- diff --git a/Source/IGListBindingSectionController.m b/Source/IGListBindingSectionController.m index b7e73296..346ff00a 100644 --- a/Source/IGListBindingSectionController.m +++ b/Source/IGListBindingSectionController.m @@ -114,7 +114,7 @@ typedef NS_ENUM(NSInteger, IGListDiffingSectionState) { self.object = object; if (oldObject == nil) { - self.viewModels = [self.dataSource sectionController:self viewModelsForObject:object]; + self.viewModels = [[self.dataSource sectionController:self viewModelsForObject:object] copy]; } 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 c5e204b7..3ac90cbd 100644 --- a/Tests/IGListBindingSectionControllerTests.m +++ b/Tests/IGListBindingSectionControllerTests.m @@ -296,5 +296,24 @@ [self waitForExpectationsWithTimeout:30 handler:nil]; } +- (void)test_whenUpdating_withMutableArrayObject_thatViewModelsDontMutate { + NSArray *objects = @[ + @"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]; + [initObjects removeAllObjects]; + + XCTAssertEqual(oldModels, section.viewModels); +} + @end