diff --git a/CHANGELOG.md b/CHANGELOG.md index bed6aaa4..ff946fcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ The changelog for `IGListKit`. Also see the [releases](https://github.com/instagram/IGListKit/releases) on GitHub. +3.2.0 (upcoming release) +----- + +### Fixes + +- 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) + + 3.1.1 ----- diff --git a/Source/IGListAdapterUpdater.m b/Source/IGListAdapterUpdater.m index 48cdee2d..25ae1c01 100644 --- a/Source/IGListAdapterUpdater.m +++ b/Source/IGListAdapterUpdater.m @@ -380,6 +380,12 @@ void convertReloadToDeleteInsert(NSMutableIndexSet *reloads, } __weak __typeof__(self) weakSelf = self; + __weak __typeof__(collectionView) weakCollectionView = collectionView; + + // dispatch_async to give the main queue time to collect more batch updates so that a minimum amount of work + // (diffing, etc) is done on main. dispatch_async does not garauntee a full runloop turn will pass though. + // see -performUpdateWithCollectionView:fromObjects:toObjects:animated:]objectTransitionBlock:completion: for more + // details on how coalescence is done. dispatch_async(dispatch_get_main_queue(), ^{ if (weakSelf.state != IGListBatchUpdateStateIdle || ![weakSelf hasChanges]) { @@ -387,9 +393,9 @@ void convertReloadToDeleteInsert(NSMutableIndexSet *reloads, } if (weakSelf.hasQueuedReloadData) { - [weakSelf performReloadDataWithCollectionView:collectionView]; + [weakSelf performReloadDataWithCollectionView:weakCollectionView]; } else { - [weakSelf performBatchUpdatesWithCollectionView:collectionView]; + [weakSelf performBatchUpdatesWithCollectionView:weakCollectionView]; } }); } diff --git a/Tests/IGListAdapterE2ETests.m b/Tests/IGListAdapterE2ETests.m index 79856ed1..48067c15 100644 --- a/Tests/IGListAdapterE2ETests.m +++ b/Tests/IGListAdapterE2ETests.m @@ -1124,6 +1124,9 @@ - (void)test_whenQueuingUpdate_withSectionControllerBatchUpdate_thatSectionControllerNotRetained { __weak id weakSectionController = nil; + __weak id weakAdapter = nil; + __weak id weakCollectionView = nil; + @autoreleasepool { IGListAdapter *adapter = [[IGListAdapter alloc] initWithUpdater:[IGListAdapterUpdater new] viewController:nil]; IGTestDelegateDataSource *dataSource = [IGTestDelegateDataSource new]; @@ -1146,9 +1149,16 @@ dataSource.objects = @[object, genTestObject(@2, @2)]; [adapter performUpdatesAnimated:YES completion:^(BOOL finished) {}]; + weakAdapter = adapter; + weakCollectionView = collectionView; weakSectionController = section; + + XCTAssertNotNil(weakAdapter); + XCTAssertNotNil(weakCollectionView); XCTAssertNotNil(weakSectionController); } + XCTAssertNil(weakAdapter); + XCTAssertNil(weakCollectionView); XCTAssertNil(weakSectionController); }