From eb9b18ada40800941e9ec96450de67481974f07c Mon Sep 17 00:00:00 2001 From: Fabio Milano Date: Thu, 18 May 2023 13:26:26 -0700 Subject: [PATCH] Added try catch for NSInternalInconsistencyException in the update transaction Summary: Added try catch for managing NSInternalInconsistencyException that are now tunneled through our assert flow Differential Revision: D45995182 fbshipit-source-id: 829d2ea3122c1ed40e25c8da36d1926d27b42418 --- .../Internal/IGListBatchUpdateTransaction.m | 40 ++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/Source/IGListKit/Internal/IGListBatchUpdateTransaction.m b/Source/IGListKit/Internal/IGListBatchUpdateTransaction.m index 51f724eb..a71926d4 100644 --- a/Source/IGListKit/Internal/IGListBatchUpdateTransaction.m +++ b/Source/IGListKit/Internal/IGListBatchUpdateTransaction.m @@ -207,12 +207,42 @@ willPerformBatchUpdatesWithCollectionView:self.collectionView [self _didPerformBatchUpdate:finished]; }; - if (self.animated) { - [self.collectionView performBatchUpdates:updates completion:completion]; - } else { - [UIView performWithoutAnimation:^{ + @try { + if (self.animated) { [self.collectionView performBatchUpdates:updates completion:completion]; - }]; + } else { + [UIView performWithoutAnimation:^{ + [self.collectionView performBatchUpdates:updates completion:completion]; + }]; + } + } + @catch (NSException *exception) { + if ([[exception name] isEqualToString:NSInternalInconsistencyException]) { + /// As part of S342566 we have to recover from crashing the app since Xcode 14.3 has shipped + /// with a different build SDK that changes the runtime behavior of -performBatchUpdates: issues. + /// When we are performing batch updates, it's on us to advance the data source to the new state + /// inside the updates closure. + /// The data source must return the old counts up until the updates closure executes, and must return + /// the new counts after the updates closure finishes executing. + /// In prior iOS releases, UICollectionView would log an error message to the console for certain cases + /// of invalid updates, and instead fall back to reloadData. Using reloadData is destructive to UI state + /// and can negatively impact performance, but this was kept the app running so far without us noticing! + /// Now that UIKit has changed this runtime behavior we are going to apply the same workaround for the crash while we work + /// with our product team to properly fix their data source changes outside of the -performBatchUpdatesBlock: + /// IGLisKit processed a new being as an assert that requires investigation, + /// since it will be processed as invalid data source state that needs a reload. + [self begin]; + return; + } else { + [self.delegate listAdapterUpdater:self.updater + collectionView:self.collectionView + willCrashWithException:exception + fromObjects:self.sectionData.fromObjects + toObjects:self.sectionData.toObjects + diffResult:diffResult + updates:(id)_actualCollectionViewUpdates]; + @throw exception; + } } }