@@ -26,34 +26,23 @@ final class DiffableDataSource: UICollectionViewDiffableDataSource<AnyHashable,
2626 // Thus, unowned is safe here.
2727 private unowned let _collectionView : UICollectionView
2828
29- private let _diffOnBackgroundQueue : Bool
30-
31- private lazy var _diffingQueue = DispatchQueue (
32- label: " com.jessesquires.ReactiveCollectionsKit " ,
33- qos: . userInteractive,
34- autoreleaseFrequency: . workItem
35- )
36-
3729 var logger : Logging ?
3830
3931 // MARK: Init
4032
4133 init (
4234 view: UICollectionView ,
43- diffOnBackgroundQueue: Bool ,
4435 cellProvider: @escaping DiffableDataSource . CellProvider ,
4536 supplementaryViewProvider: @escaping DiffableDataSource . SupplementaryViewProvider
4637 ) {
4738 self . _collectionView = view
48- self . _diffOnBackgroundQueue = diffOnBackgroundQueue
4939 super. init ( collectionView: view, cellProvider: cellProvider)
5040 self . supplementaryViewProvider = supplementaryViewProvider
5141 }
5242
53- convenience init ( view: UICollectionView , diffOnBackgroundQueue : Bool ) {
43+ convenience init ( view: UICollectionView ) {
5444 self . init (
5545 view: view,
56- diffOnBackgroundQueue: diffOnBackgroundQueue,
5746 cellProvider: { _, _, _ in nil } ,
5847 supplementaryViewProvider: { _, _, _ in nil }
5948 )
@@ -66,12 +55,8 @@ final class DiffableDataSource: UICollectionViewDiffableDataSource<AnyHashable,
6655
6756 let snapshot = DiffableSnapshot ( viewModel: viewModel)
6857 self . applySnapshotUsingReloadData ( snapshot) {
69- // UIKit guarantees `completion` is called on the main queue.
70- dispatchPrecondition ( condition: . onQueue( . main) )
71- MainActor . assumeIsolated {
72- completion ? ( )
73- self . logger? . log ( " DataSource reload snapshot completed " )
74- }
58+ completion ? ( )
59+ self . logger? . log ( " DataSource reload snapshot completed " )
7560 }
7661 }
7762
@@ -89,33 +74,18 @@ final class DiffableDataSource: UICollectionViewDiffableDataSource<AnyHashable,
8974 // We need to inspect the current collection view state first, then pass this info downstream.
9075 let visibleItemIdentifiers = self . _visibleItemIdentifiers ( )
9176
92- if self . _diffOnBackgroundQueue {
93- self . logger? . log ( " DataSource using background queue " )
94- self . _diffingQueue. async {
95- self . _applySnapshot (
96- from: source,
97- to: destination,
98- withVisibleItems: visibleItemIdentifiers,
99- animated: animated,
100- completion: completion
101- )
102- }
103- } else {
104- self . logger? . log ( " DataSource using main queue " )
105- dispatchPrecondition ( condition: . onQueue( . main) )
106- self . _applySnapshot (
107- from: source,
108- to: destination,
109- withVisibleItems: visibleItemIdentifiers,
110- animated: animated,
111- completion: completion
112- )
113- }
77+ self . _applySnapshot (
78+ from: source,
79+ to: destination,
80+ withVisibleItems: visibleItemIdentifiers,
81+ animated: animated,
82+ completion: completion
83+ )
11484 }
11585
11686 // MARK: Private
11787
118- nonisolated private func _applySnapshot(
88+ private func _applySnapshot(
11989 from source: CollectionViewModel ,
12090 to destination: CollectionViewModel ,
12191 withVisibleItems visibleItemIdentifiers: Set < UniqueIdentifier > ,
@@ -153,59 +123,49 @@ final class DiffableDataSource: UICollectionViewDiffableDataSource<AnyHashable,
153123 destinationSnapshot. reconfigureItems ( itemsToReconfigure)
154124
155125 // Apply the snapshot with item reconfigure updates.
156- //
157- // Swift 6 complains about 'call to main actor-isolated instance method' here.
158- // However, call this method from a background thread is valid according to the docs.
159126 self . apply ( destinationSnapshot, animatingDifferences: animated) { [ weak self] in
160- // UIKit guarantees `completion` is called on the main queue.
161- dispatchPrecondition ( condition: . onQueue( . main) )
162-
163127 guard let self else {
164- MainActor . assumeIsolated {
165- completion ? ( )
166- }
128+ completion ? ( )
167129 return
168130 }
169131
170- MainActor . assumeIsolated {
171- // Once the snapshot with item reconfigures is applied,
172- // we need to find and apply supplementary view reconfigures, if needed.
173- //
174- // This is necessary to update all headers, footers, and supplementary views.
175- // Per notes above, supplementary views do not get reloaded / reconfigured
176- // automatically by `DiffableDataSource` when they change.
177- //
178- // To trigger updates on supplementary views with the existing APIs,
179- // the entire section must be reloaded. Yes, that sucks. We don't want to do that.
180- // That causes all items in the section to be hard-reloaded, too.
181- // Aside from the performance impact, doing that results in an ugly UI "flash"
182- // for all item cells in the collection. Gross.
183- //
184- // However, we can actually do much better than a hard reload!
185- // Instead of reloading the entire section, we can find and compare
186- // the supplementary views and manually reconfigure them if they changed.
187- //
188- // NOTE: this only matters if supplementary views are not static.
189- // That is, if they reflect data in the data source.
190- //
191- // For example, a header with a fixed title (e.g. "My Items") will NOT need to be reloaded.
192- // However, a header that displays changing data WILL need to be reloaded.
193- // (e.g. "My 10 Items")
194-
195- // Check all the supplementary views and reconfigure them, if needed.
196- self . _reconfigureSupplementaryViewsIfNeeded ( from: source, to: destination)
197-
198- // Finally, we're done and can call completion.
199- completion ? ( )
200-
201- self . logger? . log ( " DataSource diffing snapshot complete " )
202- }
132+ // Once the snapshot with item reconfigures is applied,
133+ // we need to find and apply supplementary view reconfigures, if needed.
134+ //
135+ // This is necessary to update all headers, footers, and supplementary views.
136+ // Per notes above, supplementary views do not get reloaded / reconfigured
137+ // automatically by `DiffableDataSource` when they change.
138+ //
139+ // To trigger updates on supplementary views with the existing APIs,
140+ // the entire section must be reloaded. Yes, that sucks. We don't want to do that.
141+ // That causes all items in the section to be hard-reloaded, too.
142+ // Aside from the performance impact, doing that results in an ugly UI "flash"
143+ // for all item cells in the collection. Gross.
144+ //
145+ // However, we can actually do much better than a hard reload!
146+ // Instead of reloading the entire section, we can find and compare
147+ // the supplementary views and manually reconfigure them if they changed.
148+ //
149+ // NOTE: this only matters if supplementary views are not static.
150+ // That is, if they reflect data in the data source.
151+ //
152+ // For example, a header with a fixed title (e.g. "My Items") will NOT need to be reloaded.
153+ // However, a header that displays changing data WILL need to be reloaded.
154+ // (e.g. "My 10 Items")
155+
156+ // Check all the supplementary views and reconfigure them, if needed.
157+ self . _reconfigureSupplementaryViewsIfNeeded ( from: source, to: destination)
158+
159+ // Finally, we're done and can call completion.
160+ completion ? ( )
161+
162+ self . logger? . log ( " DataSource diffing snapshot complete " )
203163 }
204164 }
205165
206166 // MARK: Reconfiguring Cells
207167
208- nonisolated private func _findItemsToReconfigure(
168+ private func _findItemsToReconfigure(
209169 from source: CollectionViewModel ,
210170 to destination: CollectionViewModel ,
211171 withVisibleItems visibleItemIdentifiers: Set < UniqueIdentifier >
0 commit comments