From e0acffdb8268e85e866d8861259d2be038102d7e Mon Sep 17 00:00:00 2001 From: Jesse Squires Date: Wed, 9 Oct 2024 15:48:45 -0700 Subject: [PATCH] [Perf] avoid unnecessary copies of cells (#136) For very large collections, these functions can be a bottleneck for performance, causing frequent, unnecessary copies of cells and supplementary views. --- CHANGELOG.md | 1 + Sources/CollectionViewModel.swift | 14 ++++++++++++-- Sources/DiffableSnapshot.swift | 10 +++++----- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f2e59a..e92718a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ NEXT - Allow setting a `UICollectionViewDelegateFlowLayout` object to receive flow layout events from the collection view. ([@jessesquires](https://github.com/jessesquires), [#134](https://github.com/jessesquires/ReactiveCollectionsKit/pull/134)) - Swift Concurrency improvements: `@MainActor` annotations have been removed from most top-level types and protocols, instead opting to apply `@MainActor` to individual members only where necessary. The goal is to impose fewer restrictions/burdens on clients. ([@jessesquires](https://github.com/jessesquires), [#135](https://github.com/jessesquires/ReactiveCollectionsKit/pull/135)) +- Various performance improvements. ([@jessesquires](https://github.com/jessesquires), [#136](https://github.com/jessesquires/ReactiveCollectionsKit/pull/136)) 0.1.7 ----- diff --git a/Sources/CollectionViewModel.swift b/Sources/CollectionViewModel.swift index eb8c976..def1ef9 100644 --- a/Sources/CollectionViewModel.swift +++ b/Sources/CollectionViewModel.swift @@ -70,7 +70,12 @@ public struct CollectionViewModel: Hashable, DiffableViewModel { /// - Parameter id: The identifier for the cell. /// - Returns: The cell, if it exists. public func cellViewModel(for id: UniqueIdentifier) -> AnyCellViewModel? { - self.flatMap(\.cells).first { $0.id == id } + for section in self.sections { + for cell in section.cells where cell.id == id { + return cell + } + } + return nil } /// Returns the cell at the specified index path. @@ -96,7 +101,12 @@ public struct CollectionViewModel: Hashable, DiffableViewModel { /// - Parameter id: The identifier for the supplementary view. /// - Returns: The supplementary view, if it exists. public func supplementaryViewModel(for id: UniqueIdentifier) -> AnySupplementaryViewModel? { - self.flatMap(\.supplementaryViews).first { $0.id == id } + for section in self.sections { + for view in section.supplementaryViews where view.id == id { + return view + } + } + return nil } /// Returns the supplementary view for the specified kind and index path. diff --git a/Sources/DiffableSnapshot.swift b/Sources/DiffableSnapshot.swift index 3f67ba9..1372b26 100644 --- a/Sources/DiffableSnapshot.swift +++ b/Sources/DiffableSnapshot.swift @@ -21,12 +21,12 @@ extension DiffableSnapshot { init(viewModel: CollectionViewModel) { self.init() - let allSectionIdentifiers = viewModel.sections.map(\.id) - self.appendSections(allSectionIdentifiers) + for section in viewModel.sections { + self.appendSections([section.id]) - viewModel.sections.forEach { - let allCellIdentifiers = $0.cells.map(\.id) - self.appendItems(allCellIdentifiers, toSection: $0.id) + for cell in section { + self.appendItems([cell.id], toSection: section.id) + } } } }