diff --git a/CHANGELOG.md b/CHANGELOG.md index b088ba8a..0ef0eff5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 insets as they may be incorrect. - Pass initial size to embedded view from `CollectionViewCell`/`CollectionViewReusableView` to better load embedded SwiftUI views. +- Guard against a UIKit crash caused by attempting to scroll to an item that no longer exists. ## [0.9.0](https://github.com/airbnb/epoxy-ios/compare/0.8.0...0.9.0) - 2022-10-25 diff --git a/Sources/EpoxyCollectionView/CollectionView/Internal/CollectionViewScrollToItemHelper.swift b/Sources/EpoxyCollectionView/CollectionView/Internal/CollectionViewScrollToItemHelper.swift index 18a26749..ceeaa096 100644 --- a/Sources/EpoxyCollectionView/CollectionView/Internal/CollectionViewScrollToItemHelper.swift +++ b/Sources/EpoxyCollectionView/CollectionView/Internal/CollectionViewScrollToItemHelper.swift @@ -154,12 +154,25 @@ final class CollectionViewScrollToItemHelper { { self.scrollToItemContext = nil - collectionView?.scrollToItem( - at: scrollToItemContext.targetIndexPath, - at: scrollToItemContext.targetScrollPosition, - animated: animated) + guard let collectionView = collectionView else { return } + + // Calling `scrollToItem(…)` with in invalid index path raises an exception: + // > NSInternalInconsistencyException: Attempted to scroll the collection view to an out-of- + // > bounds item + // We must guard against this to check to ensure that this never happens, as we call this method + // repeatedly and the items/section may change out from under us. + if + case let indexPath = scrollToItemContext.targetIndexPath, + indexPath.section < collectionView.numberOfSections, + indexPath.item < collectionView.numberOfItems(inSection: indexPath.section) + { + collectionView.scrollToItem( + at: indexPath, + at: scrollToItemContext.targetScrollPosition, + animated: animated) + } - if let collectionView = collectionView, !animated { + if !animated { collectionView.delegate?.scrollViewDidEndScrollingAnimation?(collectionView) } }