Skip to content

Commit 6814598

Browse files
SectionController support: opt-out from Items changes animation (#129)
Provide support to opt-out from animations for Section updates. The implementation 1. Leaves the animations opted in by default. 2. When needed the section controller can override the method and return false/true
2 parents de17f68 + aba2b71 commit 6814598

File tree

5 files changed

+71
-0
lines changed

5 files changed

+71
-0
lines changed

SectionKit/Sources/SectionController/Generic/ListSectionController.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,26 @@ open class ListSectionController<Model, Item>: BaseSectionController {
106106
CollectionViewSectionUpdate(
107107
controller: self,
108108
data: newData,
109+
shouldAnimate: shouldAnimateItems(from: oldData, to: newData),
109110
setData: { self.collectionViewItems = $0 }
110111
)
111112
}
112113

114+
/**
115+
Controlls where the update from old to new data should be animated.
116+
117+
- Parameter oldData: The old data currently displayed in the section.
118+
119+
- Parameter newData: The new data that should be displayed in the section.
120+
121+
- Returns: Bool. Default true.
122+
*/
123+
open func shouldAnimateItems(
124+
from oldData: [Item],
125+
to newData: [Item]
126+
) -> Bool {
127+
return true
128+
}
129+
113130
override open func numberOfItems(in context: CollectionViewContext) -> Int { items.count }
114131
}

SectionKit/Sources/SectionController/Generic/SingleItemSectionController.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,30 @@ open class SingleItemSectionController<Model, Item>: BaseSectionController {
123123
return CollectionViewSectionUpdate(
124124
controller: self,
125125
data: newData,
126+
shouldAnimate: shouldAnimateItems(from: oldData, to: newData),
126127
deletes: deletes,
127128
inserts: inserts,
128129
reloads: reloads,
129130
setData: { self.collectionViewItem = $0 }
130131
)
131132
}
132133

134+
/**
135+
Controlls where the update from old to new data should be animated.
136+
137+
- Parameter oldData: The old data currently displayed in the section.
138+
139+
- Parameter newData: The new data that should be displayed in the section.
140+
141+
- Returns: Bool. Default true.
142+
*/
143+
open func shouldAnimateItems(
144+
from oldData:Item?,
145+
to newData: Item?
146+
) -> Bool {
147+
return true
148+
}
149+
133150
override open func numberOfItems(in context: CollectionViewContext) -> Int { item != nil ? 1 : 0 }
134151
}
135152

SectionKit/Sources/SectionController/Generic/SingleModelSectionController.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,26 @@ open class SingleModelSectionController<Model>: BaseSectionController {
7070
CollectionViewSectionUpdate(
7171
controller: self,
7272
data: newData,
73+
shouldAnimate: shouldAnimateItems(from: oldData, to: newData),
7374
setData: { self.collectionViewModel = $0 }
7475
)
7576
}
77+
78+
/**
79+
Controlls where the update from old to new data should be animated.
80+
81+
- Parameter oldData: The old data currently displayed in the section.
82+
83+
- Parameter newData: The new data that should be displayed in the section.
84+
85+
- Returns: Bool. Default true.
86+
*/
87+
open func shouldAnimateItems(
88+
from oldData: Model,
89+
to newData: Model
90+
) -> Bool {
91+
return true
92+
}
7693

7794
override open func numberOfItems(in context: CollectionViewContext) -> Int { 1 }
7895
}

SectionKit/Sources/SectionController/Update/CollectionViewSectionUpdate.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ public struct CollectionViewSectionUpdate<SectionData> {
99

1010
/// The batch operations that should be performed in succession.
1111
public let batchOperations: [BatchOperation]
12+
13+
/// weather the changes should be aniamted
14+
public let shouldAnimate: Bool
1215

1316
/// A handler that gets executed inside a batch operation to set the backing data of the current batch of updates.
1417
public let setData: @MainActor (SectionData) -> Void
@@ -40,11 +43,13 @@ public struct CollectionViewSectionUpdate<SectionData> {
4043
public init(
4144
controller: SectionController,
4245
batchOperations: [BatchOperation],
46+
shouldAnimate: Bool = true,
4347
setData: @escaping @MainActor (SectionData) -> Void,
4448
shouldReload: @escaping @MainActor (BatchOperation) -> Bool = { _ in false }
4549
) {
4650
self.controller = controller
4751
self.batchOperations = batchOperations
52+
self.shouldAnimate = shouldAnimate
4853
self.setData = setData
4954
self.shouldReload = shouldReload
5055
}
@@ -79,6 +84,7 @@ public struct CollectionViewSectionUpdate<SectionData> {
7984
public init(
8085
controller: SectionController,
8186
data: SectionData,
87+
shouldAnimate: Bool = true,
8288
deletes: Set<Int> = [],
8389
inserts: Set<Int> = [],
8490
moves: Set<Move> = [],
@@ -98,6 +104,7 @@ public struct CollectionViewSectionUpdate<SectionData> {
98104
self.init(
99105
controller: controller,
100106
batchOperations: [batchOperation],
107+
shouldAnimate: shouldAnimate,
101108
setData: setData,
102109
shouldReload: shouldReload
103110
)
@@ -120,12 +127,14 @@ public struct CollectionViewSectionUpdate<SectionData> {
120127
public init(
121128
controller: SectionController,
122129
data: SectionData,
130+
shouldAnimate: Bool = true,
123131
setData: @escaping @MainActor (SectionData) -> Void,
124132
completion: (@MainActor (Bool) -> Void)? = nil
125133
) {
126134
self.init(
127135
controller: controller,
128136
data: data,
137+
shouldAnimate: shouldAnimate,
129138
setData: setData,
130139
shouldReload: { _ in true },
131140
completion: completion

SectionKit/Sources/Utility/UICollectionView+Apply.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,17 @@ extension UICollectionView {
2424
return
2525
}
2626

27+
guard update.shouldAnimate else {
28+
for batchOperation in update.batchOperations {
29+
update.setData(batchOperation.data)
30+
UIView.performWithoutAnimation {
31+
reloadSections(IndexSet(integer: section))
32+
}
33+
batchOperation.completion?(false)
34+
}
35+
return
36+
}
37+
2738
for batchOperation in update.batchOperations {
2839
performBatchUpdates({
2940
update.setData(batchOperation.data)

0 commit comments

Comments
 (0)