Skip to content

Commit be1cd5b

Browse files
committed
Add completion handlers to the UIKit extensions
1 parent f8c8d1e commit be1cd5b

File tree

2 files changed

+58
-14
lines changed

2 files changed

+58
-14
lines changed

Sources/Extensions/AppKitExtension.swift

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,23 @@ public extension NSTableView {
1515
/// updates should be stopped and performed reloadData. Default is nil.
1616
/// - setData: A closure that takes the collection as a parameter.
1717
/// The collection should be set to data-source of NSTableView.
18+
/// - completion: A closure that is called when the reload is completed.
1819

1920
func reload<C>(
2021
using stagedChangeset: StagedChangeset<C>,
2122
with animation: @autoclosure () -> NSTableView.AnimationOptions,
2223
interrupt: ((Changeset<C>) -> Bool)? = nil,
23-
setData: (C) -> Void
24+
setData: (C) -> Void,
25+
completion: (() -> Void)? = nil
2426
) {
2527
reload(
2628
using: stagedChangeset,
2729
deleteRowsAnimation: animation(),
2830
insertRowsAnimation: animation(),
2931
reloadRowsAnimation: animation(),
3032
interrupt: interrupt,
31-
setData: setData
33+
setData: setData,
34+
completion: completion
3235
)
3336
}
3437

@@ -47,14 +50,21 @@ public extension NSTableView {
4750
/// updates should be stopped and performed reloadData. Default is nil.
4851
/// - setData: A closure that takes the collection as a parameter.
4952
/// The collection should be set to data-source of NSTableView.
53+
/// - completion: A closure that is called when the reload is completed.
5054
func reload<C>(
5155
using stagedChangeset: StagedChangeset<C>,
5256
deleteRowsAnimation: @autoclosure () -> NSTableView.AnimationOptions,
5357
insertRowsAnimation: @autoclosure () -> NSTableView.AnimationOptions,
5458
reloadRowsAnimation: @autoclosure () -> NSTableView.AnimationOptions,
5559
interrupt: ((Changeset<C>) -> Bool)? = nil,
56-
setData: (C) -> Void
60+
setData: (C) -> Void,
61+
completion: (() -> Void)? = nil
5762
) {
63+
let group = DispatchGroup()
64+
defer {
65+
group.notify(queue: .main) { completion?() }
66+
}
67+
5868
if case .none = window, let data = stagedChangeset.last?.data {
5969
setData(data)
6070
return reloadData()
@@ -66,6 +76,9 @@ public extension NSTableView {
6676
return reloadData()
6777
}
6878

79+
group.enter()
80+
CATransaction.begin()
81+
CATransaction.setCompletionBlock({ group.leave() })
6982
beginUpdates()
7083
setData(changeset.data)
7184

@@ -86,6 +99,7 @@ public extension NSTableView {
8699
}
87100

88101
endUpdates()
102+
CATransaction.commit()
89103
}
90104
}
91105
}
@@ -104,11 +118,18 @@ public extension NSCollectionView {
104118
/// updates should be stopped and performed reloadData. Default is nil.
105119
/// - setData: A closure that takes the collection as a parameter.
106120
/// The collection should be set to data-source of NSCollectionView.
121+
/// - completion: A closure that is called when the reload is completed.
107122
func reload<C>(
108123
using stagedChangeset: StagedChangeset<C>,
109124
interrupt: ((Changeset<C>) -> Bool)? = nil,
110-
setData: (C) -> Void
125+
setData: (C) -> Void,
126+
completion: (() -> Void)? = nil
111127
) {
128+
let group = DispatchGroup()
129+
defer {
130+
group.notify(queue: .main) { completion?() }
131+
}
132+
112133
if case .none = window, let data = stagedChangeset.last?.data {
113134
setData(data)
114135
return reloadData()
@@ -120,6 +141,7 @@ public extension NSCollectionView {
120141
return reloadData()
121142
}
122143

144+
group.enter()
123145
animator().performBatchUpdates({
124146
setData(changeset.data)
125147

@@ -138,7 +160,7 @@ public extension NSCollectionView {
138160
for (source, target) in changeset.elementMoved {
139161
moveItem(at: IndexPath(item: source.element, section: source.section), to: IndexPath(item: target.element, section: target.section))
140162
}
141-
})
163+
}, completionHandler: { _ in group.leave() })
142164
}
143165
}
144166
}

Sources/Extensions/UIKitExtension.swift

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ public extension UITableView {
1515
/// updates should be stopped and performed reloadData. Default is nil.
1616
/// - setData: A closure that takes the collection as a parameter.
1717
/// The collection should be set to data-source of UITableView.
18+
/// - completion: A closure that is called when the reload is completed.
1819
func reload<C>(
1920
using stagedChangeset: StagedChangeset<C>,
2021
with animation: @autoclosure () -> RowAnimation,
2122
interrupt: ((Changeset<C>) -> Bool)? = nil,
22-
setData: (C) -> Void
23+
setData: (C) -> Void,
24+
completion: (() -> Void)? = nil
2325
) {
2426
reload(
2527
using: stagedChangeset,
@@ -30,7 +32,8 @@ public extension UITableView {
3032
insertRowsAnimation: animation(),
3133
reloadRowsAnimation: animation(),
3234
interrupt: interrupt,
33-
setData: setData
35+
setData: setData,
36+
completion: completion
3437
)
3538
}
3639

@@ -52,6 +55,7 @@ public extension UITableView {
5255
/// updates should be stopped and performed reloadData. Default is nil.
5356
/// - setData: A closure that takes the collection as a parameter.
5457
/// The collection should be set to data-source of UITableView.
58+
/// - completion: A closure that is called when the reload is completed.
5559
func reload<C>(
5660
using stagedChangeset: StagedChangeset<C>,
5761
deleteSectionsAnimation: @autoclosure () -> RowAnimation,
@@ -61,8 +65,14 @@ public extension UITableView {
6165
insertRowsAnimation: @autoclosure () -> RowAnimation,
6266
reloadRowsAnimation: @autoclosure () -> RowAnimation,
6367
interrupt: ((Changeset<C>) -> Bool)? = nil,
64-
setData: (C) -> Void
68+
setData: (C) -> Void,
69+
completion: (() -> Void)? = nil
6570
) {
71+
let group = DispatchGroup()
72+
defer {
73+
group.notify(queue: .main) { completion?() }
74+
}
75+
6676
if case .none = window, let data = stagedChangeset.last?.data {
6777
setData(data)
6878
return reloadData()
@@ -74,7 +84,8 @@ public extension UITableView {
7484
return reloadData()
7585
}
7686

77-
_performBatchUpdates {
87+
group.enter()
88+
_performBatchUpdates({
7889
setData(changeset.data)
7990

8091
if !changeset.sectionDeleted.isEmpty {
@@ -108,18 +119,21 @@ public extension UITableView {
108119
for (source, target) in changeset.elementMoved {
109120
moveRow(at: IndexPath(row: source.element, section: source.section), to: IndexPath(row: target.element, section: target.section))
110121
}
111-
}
122+
}, completion: { group.leave() })
112123
}
113124
}
114125

115-
private func _performBatchUpdates(_ updates: () -> Void) {
126+
private func _performBatchUpdates(_ updates: () -> Void, completion: (() -> Void)?) {
116127
if #available(iOS 11.0, tvOS 11.0, *) {
117-
performBatchUpdates(updates)
128+
performBatchUpdates(updates, completion: { _ in completion?() })
118129
}
119130
else {
131+
CATransaction.begin()
132+
CATransaction.setCompletionBlock(completion)
120133
beginUpdates()
121134
updates()
122135
endUpdates()
136+
CATransaction.commit()
123137
}
124138
}
125139
}
@@ -137,11 +151,18 @@ public extension UICollectionView {
137151
/// updates should be stopped and performed reloadData. Default is nil.
138152
/// - setData: A closure that takes the collection as a parameter.
139153
/// The collection should be set to data-source of UICollectionView.
154+
/// - completion: A closure that is called when the reload is completed.
140155
func reload<C>(
141156
using stagedChangeset: StagedChangeset<C>,
142157
interrupt: ((Changeset<C>) -> Bool)? = nil,
143-
setData: (C) -> Void
158+
setData: (C) -> Void,
159+
completion: (() -> Void)? = nil
144160
) {
161+
let group = DispatchGroup()
162+
defer {
163+
group.notify(queue: .main) { completion?() }
164+
}
165+
145166
if case .none = window, let data = stagedChangeset.last?.data {
146167
setData(data)
147168
return reloadData()
@@ -153,6 +174,7 @@ public extension UICollectionView {
153174
return reloadData()
154175
}
155176

177+
group.enter()
156178
performBatchUpdates({
157179
setData(changeset.data)
158180

@@ -187,7 +209,7 @@ public extension UICollectionView {
187209
for (source, target) in changeset.elementMoved {
188210
moveItem(at: IndexPath(item: source.element, section: source.section), to: IndexPath(item: target.element, section: target.section))
189211
}
190-
})
212+
}, completion: { _ in group.leave() })
191213
}
192214
}
193215
}

0 commit comments

Comments
 (0)