Skip to content

Commit 048f522

Browse files
author
Stephane Magne
authored
Merge pull request #11 from scribd/stephane/update_animation_delegate
Update CollectionDataAnimationDelegate to give more timing options. Update minimum version to iOS 11.
2 parents e9e3917 + 14e601e commit 048f522

File tree

8 files changed

+122
-164
lines changed

8 files changed

+122
-164
lines changed

LiveCollections.xcodeproj/project.pbxproj

+2-4
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@
541541
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
542542
GCC_WARN_UNUSED_FUNCTION = YES;
543543
GCC_WARN_UNUSED_VARIABLE = YES;
544-
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
544+
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
545545
MTL_ENABLE_DEBUG_INFO = YES;
546546
ONLY_ACTIVE_ARCH = YES;
547547
SDKROOT = iphoneos;
@@ -598,7 +598,7 @@
598598
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
599599
GCC_WARN_UNUSED_FUNCTION = YES;
600600
GCC_WARN_UNUSED_VARIABLE = YES;
601-
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
601+
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
602602
MTL_ENABLE_DEBUG_INFO = NO;
603603
SDKROOT = iphoneos;
604604
SWIFT_COMPILATION_MODE = wholemodule;
@@ -622,7 +622,6 @@
622622
DYLIB_INSTALL_NAME_BASE = "@rpath";
623623
INFOPLIST_FILE = Info.plist;
624624
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
625-
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
626625
LD_RUNPATH_SEARCH_PATHS = (
627626
"$(inherited)",
628627
"@executable_path/Frameworks",
@@ -650,7 +649,6 @@
650649
DYLIB_INSTALL_NAME_BASE = "@rpath";
651650
INFOPLIST_FILE = Info.plist;
652651
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
653-
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
654652
LD_RUNPATH_SEARCH_PATHS = (
655653
"$(inherited)",
656654
"@executable_path/Frameworks",

LiveCollectionsSample/LiveCollectionsSample/Source/Scenarios/Scenario ViewControllers/ScenarioSeven/CarouselController.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ extension CarouselController: CollectionDataAnimationDelegate {
112112
return .preciseAnimations
113113
}
114114

115-
func animateAlongsideUpdate(with duration: TimeInterval) {
115+
func animateAlongsideUpdate(for state: CollectionDataAnimationState) {
116116
// animate alongside the collection view animation here
117117
}
118118
}

LiveCollectionsSample/LiveCollectionsSample/Source/Scenarios/Scenario ViewControllers/ScenarioSeven/ScenarioSevenViewController.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ extension ScenarioSevenViewController: CollectionDataAnimationDelegate {
100100
return .preciseAnimations
101101
}
102102

103-
func animateAlongsideUpdate(with duration: TimeInterval) {
103+
func animateAlongsideUpdate(for state: CollectionDataAnimationState) {
104104
// animate alongside the table view animation here
105105
}
106106
}

LiveCollectionsSample/LiveCollectionsSample/Source/Scenarios/Scenario ViewControllers/ScenarioThreeViewController.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ extension ScenarioThreeViewController: CollectionDataAnimationDelegate {
131131
return .preciseAnimations
132132
}
133133

134-
func animateAlongsideUpdate(with duration: TimeInterval) {
134+
func animateAlongsideUpdate(for state: CollectionDataAnimationState) {
135135
// animate alongside the collection view animation here
136136
// use a CollectionDataSynchronizer object if you would like
137137
// all animations to map to a single call

Sources/LiveCollections/Classes/Internal/AnyProtocols/AnyDeltaUpdatableViewDelegate.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ extension AnyDeltaUpdatableViewDelegate: DeltaUpdatableViewDelegate {
4242
return animationDelegate?.preferredItemAnimationStyle(for: itemDelta) ?? .preciseAnimations
4343
}
4444

45-
func animateAlongsideUpdate(with duration: TimeInterval) {
46-
animationDelegate?.animateAlongsideUpdate(with: duration)
45+
func animateAlongsideUpdate(for state: CollectionDataAnimationState) {
46+
animationDelegate?.animateAlongsideUpdate(for: state)
4747
}
4848

4949
var view: DeltaUpdatableView? {
@@ -79,8 +79,8 @@ extension AnySectionDeltaUpdatableViewDelegate: SectionDeltaUpdatableViewDelegat
7979
return animationDelegate?.preferredItemAnimationStyle(for: itemDelta) ?? .preciseAnimations
8080
}
8181

82-
func animateAlongsideUpdate(with duration: TimeInterval) {
83-
animationDelegate?.animateAlongsideUpdate(with: duration)
82+
func animateAlongsideUpdate(for state: CollectionDataAnimationState) {
83+
animationDelegate?.animateAlongsideUpdate(for: state)
8484
}
8585

8686
func preferredSectionAnimationStyle(for sectionDelta: IndexDelta) -> AnimationStyle {

Sources/LiveCollections/Classes/Public/Delegate/CollectionDataDelegate.swift

+14-2
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,26 @@ public protocol CollectionDataCalculationNotificationDelegate: AnyObject {
6767
func collectionDataDidEndCalculating()
6868
}
6969

70-
// MARK: CollectionDataCalculationNotificationDelegate
70+
// MARK: CollectionDataAnimationDelegate
71+
72+
public enum CollectionDataAnimationGroup {
73+
case insertDeleteMove
74+
case reload
75+
}
76+
77+
public enum CollectionDataAnimationState {
78+
case immediatelyBefore(group: CollectionDataAnimationGroup, duration: TimeInterval)
79+
case immediatelyAfter(group: CollectionDataAnimationGroup, duration: TimeInterval)
80+
case during(group: CollectionDataAnimationGroup, duration: TimeInterval)
81+
case completed(group: CollectionDataAnimationGroup)
82+
}
7183

7284
/**
7385
Use to control the style of animations or to animate alongside a UITableView or UICollectionView animation
7486
*/
7587
public protocol CollectionDataAnimationDelegate: AnyObject {
7688
func preferredItemAnimationStyle(for itemDelta: IndexDelta) -> AnimationStyle
77-
func animateAlongsideUpdate(with duration: TimeInterval)
89+
func animateAlongsideUpdate(for state: CollectionDataAnimationState)
7890
}
7991

8092
// MARK: CollectionSectionDataAnimationDelegate

Sources/LiveCollections/Classes/Public/UIKit & Foundatin Extensions/UIKit+DeltaUpdates.swift

+66-66
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,25 @@ extension UITableView: DeltaUpdatableView {
6666
}
6767
}
6868

69-
if #available(iOS 11.0, *) {
70-
performBatchUpdates({ [weak self] in
71-
tableViewUpdates.forEach { $0.sectionUpdate.update() }
72-
guard self != nil else { return }
73-
deleteMoveInsert()
74-
tableViewUpdates.uniqueAnimationDelegates.forEach { $0.animateAlongsideUpdate(with: TimeInterval.standardCollectionAnimationDuration) }
75-
}, completion: { [weak self] animationsCompletedSuccessfully in
76-
guard let strongSelf = self else {
69+
performBatchUpdates(.insertDeleteMove, delegates: tableViewUpdates.uniqueAnimationDelegates, { [weak self] in
70+
tableViewUpdates.forEach { $0.sectionUpdate.update() }
71+
guard self != nil else { return }
72+
deleteMoveInsert()
73+
}, completion: { [weak self] animationsCompletedSuccessfully in
74+
guard let strongSelf = self else {
75+
tableViewUpdates.forEach { $0.sectionUpdate.completion?() }
76+
return
77+
}
78+
guard animationsCompletedSuccessfully else {
79+
strongSelf.reloadData()
80+
tableViewUpdates.forEach { $0.sectionUpdate.completion?() }
81+
return
82+
}
83+
strongSelf.performBatchUpdates(.reload, delegates: tableViewUpdates.uniqueAnimationDelegates, { [weak weakSelf = strongSelf] in
84+
guard weakSelf != nil else { return }
85+
reload()
86+
}, completion: { [weak weakSelf = strongSelf] animationsCompletedSuccessfully in
87+
guard let strongSelf = weakSelf else {
7788
tableViewUpdates.forEach { $0.sectionUpdate.completion?() }
7889
return
7990
}
@@ -82,73 +93,27 @@ extension UITableView: DeltaUpdatableView {
8293
tableViewUpdates.forEach { $0.sectionUpdate.completion?() }
8394
return
8495
}
85-
strongSelf.performBatchUpdates({ [weak weakSelf = strongSelf] in
86-
guard weakSelf != nil else { return }
87-
reload()
88-
}, completion: { [weak weakSelf = strongSelf] animationsCompletedSuccessfully in
89-
guard let strongSelf = weakSelf else {
90-
tableViewUpdates.forEach { $0.sectionUpdate.completion?() }
91-
return
92-
}
93-
guard animationsCompletedSuccessfully else {
94-
strongSelf.reloadData()
95-
tableViewUpdates.forEach { $0.sectionUpdate.completion?() }
96-
return
97-
}
98-
99-
tableViewUpdates.manualReload(view: strongSelf) {
100-
tableViewUpdates.forEach { $0.sectionUpdate.completion?() }
101-
}
102-
})
103-
})
104-
} else {
105-
beginUpdates()
106-
tableViewUpdates.forEach { $0.sectionUpdate.update() }
107-
deleteMoveInsert()
108-
tableViewUpdates.uniqueAnimationDelegates.forEach { $0.animateAlongsideUpdate(with: TimeInterval.standardCollectionAnimationDuration) }
109-
endUpdates()
110-
111-
guard isVisibleOnScreen else {
112-
reloadData()
113-
tableViewUpdates.forEach { $0.sectionUpdate.completion?() }
114-
return
115-
}
11696

117-
beginUpdates()
118-
reload()
119-
endUpdates()
120-
121-
tableViewUpdates.manualReload(view: self) {
122-
tableViewUpdates.forEach { $0.sectionUpdate.completion?() }
123-
}
124-
}
97+
tableViewUpdates.manualReload(view: strongSelf) {
98+
tableViewUpdates.forEach { $0.sectionUpdate.completion?() }
99+
}
100+
})
101+
})
125102
}
126103

127104
public func reloadSections(for sectionUpdates: [SectionUpdate]) {
128105

129-
if #available(iOS 11.0, *) {
130-
performBatchUpdates({ [weak self] in
131-
sectionUpdates.forEach { sectionUpdate in
132-
sectionUpdate.update()
133-
guard self != nil else { return }
134-
let indexSet = IndexSet([sectionUpdate.section])
135-
reloadSections(indexSet, with: preferredReloadSectionAnimation(for: sectionUpdate.section))
136-
}
137-
sectionUpdates.uniqueAnimationDelegates.forEach { $0.animateAlongsideUpdate(with: TimeInterval.standardCollectionAnimationDuration) }
138-
}, completion: { _ in
139-
sectionUpdates.forEach { $0.completion?() }
140-
})
141-
} else {
142-
beginUpdates()
106+
performBatchUpdates({ [weak self] in
143107
sectionUpdates.forEach { sectionUpdate in
144108
sectionUpdate.update()
109+
guard self != nil else { return }
145110
let indexSet = IndexSet([sectionUpdate.section])
146111
reloadSections(indexSet, with: preferredReloadSectionAnimation(for: sectionUpdate.section))
147112
}
148113
sectionUpdates.uniqueAnimationDelegates.forEach { $0.animateAlongsideUpdate(with: TimeInterval.standardCollectionAnimationDuration) }
149-
endUpdates()
114+
}, completion: { _ in
150115
sectionUpdates.forEach { $0.completion?() }
151-
}
116+
})
152117
}
153118
}
154119

@@ -189,7 +154,7 @@ extension UICollectionView: DeltaUpdatableView {
189154
return
190155
}
191156

192-
performBatchUpdates({ [weak self] in
157+
performBatchUpdates(.insertDeleteMove, delegates: collectionViewUpdates.uniqueAnimationDelegates, { [weak self] in
193158
collectionViewUpdates.forEach { $0.sectionUpdate.update() }
194159
guard let strongSelf = self else { return }
195160
for update in collectionViewUpdates {
@@ -201,7 +166,6 @@ extension UICollectionView: DeltaUpdatableView {
201166
}
202167
strongSelf.insertItems(at: delta.insertedIndexPaths)
203168
}
204-
collectionViewUpdates.uniqueAnimationDelegates.forEach { $0.animateAlongsideUpdate(with: TimeInterval.standardCollectionAnimationDuration) }
205169
}, completion: { [weak self] animationsCompletedSuccessfully in
206170
guard let strongSelf = self else {
207171
collectionViewUpdates.forEach { $0.sectionUpdate.completion?() }
@@ -219,7 +183,7 @@ extension UICollectionView: DeltaUpdatableView {
219183
return
220184
}
221185

222-
strongSelf.performBatchUpdates({ [weak weakSelf = strongSelf] in
186+
strongSelf.performBatchUpdates(.reload, delegates: collectionViewUpdates.uniqueAnimationDelegates, { [weak weakSelf = strongSelf] in
223187
guard let strongSelf = weakSelf else { return }
224188
for update in filteredUpdates {
225189
let delta = update.indexPathsToAnimate
@@ -497,3 +461,39 @@ private extension Sequence where Element == SectionUpdate {
497461
})
498462
}
499463
}
464+
465+
// MARK: AnimationDelegate Helper
466+
467+
private extension UITableView {
468+
469+
func performBatchUpdates(_ group: CollectionDataAnimationGroup, delegates: [CollectionDataAnimationDelegate], _ updates: (() -> Void)?, completion: ((Bool) -> Void)? = nil) {
470+
delegates.forEach { $0.animateAlongsideUpdate(for: .immediatelyBefore(group: group, duration: TimeInterval.standardCollectionAnimationDuration)) }
471+
472+
performBatchUpdates {
473+
updates?()
474+
delegates.forEach { $0.animateAlongsideUpdate(for: .during(group: group, duration: TimeInterval.standardCollectionAnimationDuration)) }
475+
} completion: { value in
476+
completion?(value)
477+
delegates.forEach { $0.animateAlongsideUpdate(for: .completed(group: group)) }
478+
}
479+
480+
delegates.forEach { $0.animateAlongsideUpdate(for: .immediatelyAfter(group: group, duration: TimeInterval.standardCollectionAnimationDuration)) }
481+
}
482+
}
483+
484+
private extension UICollectionView {
485+
486+
func performBatchUpdates(_ group: CollectionDataAnimationGroup, delegates: [CollectionDataAnimationDelegate], _ updates: (() -> Void)?, completion: ((Bool) -> Void)? = nil) {
487+
delegates.forEach { $0.animateAlongsideUpdate(for: .immediatelyBefore(group: group, duration: TimeInterval.standardCollectionAnimationDuration)) }
488+
489+
performBatchUpdates {
490+
updates?()
491+
delegates.forEach { $0.animateAlongsideUpdate(for: .during(group: group, duration: TimeInterval.standardCollectionAnimationDuration)) }
492+
} completion: { value in
493+
completion?(value)
494+
delegates.forEach { $0.animateAlongsideUpdate(for: .completed(group: group)) }
495+
}
496+
497+
delegates.forEach { $0.animateAlongsideUpdate(for: .immediatelyAfter(group: group, duration: TimeInterval.standardCollectionAnimationDuration)) }
498+
}
499+
}

0 commit comments

Comments
 (0)