Skip to content

Commit 21e8053

Browse files
committed
updated
1 parent 902f13a commit 21e8053

File tree

4 files changed

+78
-13
lines changed

4 files changed

+78
-13
lines changed

Sources/AdvancedCollectionTableView-iOS/CollectionView/DataSource/UICollectionViewDiffableDataSource+.swift

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ extension UICollectionViewDiffableDataSource {
8686
set(associatedValue: newValue, key: "emptyView", object: self)
8787
if newValue != nil {
8888
emptyContentConfiguration = nil
89-
updateEmptyView()
89+
updateEmptyView(snapshot())
9090
}
9191
}
9292
}
@@ -115,29 +115,49 @@ extension UICollectionViewDiffableDataSource {
115115
} else {
116116
emptyContentView = .init(configuration: configuration)
117117
}
118-
updateEmptyView()
118+
updateEmptyView(snapshot())
119119
} else {
120120
emptyContentView?.removeFromSuperview()
121121
emptyContentView = nil
122122
}
123123
}
124124
}
125125

126+
/**
127+
The handler that gets called when the data source is switching between an empty and non-empty snapshot or viceversa.
128+
129+
You can use this handler e.g. if you want to update your empty view or content configuration.
130+
*/
131+
public var emptyHandler: ((_ isEmpty: Bool)->())? {
132+
get { getAssociatedValue(key: "emptyHandler", object: self, initialValue: nil) }
133+
set {
134+
set(associatedValue: newValue, key: "emptyHandler", object: self)
135+
if let emptyHandler = newValue {
136+
emptyHandler(snapshot().isEmpty)
137+
}
138+
}
139+
}
140+
126141
var emptyContentView: ContentConfigurationView? {
127142
get { getAssociatedValue(key: "emptyContentView", object: self, initialValue: nil) }
128143
set { set(associatedValue: newValue, key: "emptyContentView", object: self) }
129144
}
130145

131-
func updateEmptyView() {
132-
let snapshot = snapshot()
133-
if !snapshot.itemIdentifiers.isEmpty && !snapshot.sectionIdentifiers.isEmpty {
146+
func updateEmptyView(_ snapshot: NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>, previousIsEmpty: Bool? = nil) {
147+
if !snapshot.isEmpty {
134148
emptyView?.removeFromSuperview()
135149
emptyContentView?.removeFromSuperview()
136150
} else if let emptyView = self.emptyView, emptyView.superview != collectionView {
137151
collectionView?.addSubview(withConstraint: emptyView)
138152
} else if let emptyContentView = self.emptyContentView, emptyContentView.superview != collectionView {
139153
collectionView?.addSubview(withConstraint: emptyContentView)
140154
}
155+
if let emptyHandler = self.emptyHandler, let previousIsEmpty = previousIsEmpty {
156+
let isEmpty = snapshot.isEmpty
157+
if previousIsEmpty != isEmpty {
158+
emptyHandler(isEmpty)
159+
}
160+
}
141161
}
142162

143163
var delegate: Delegate? {

Sources/AdvancedCollectionTableView-iOS/CollectionView/DataSource/UICollectionViewDiffableDataSource+Registration.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ public extension UICollectionViewDiffableDataSource {
3232
- completion: An optional closure to be executed when the animations are complete. This closure has no return value and takes no parameters. The system calls this closure from the main queue. The default value is `nil`.
3333
*/
3434
func apply(_ snapshot: NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>, _ option: DiffableDataSourceSnapshotApplyOption, completion: (() -> Void)? = nil) {
35+
var previousIsEmpty: Bool?
36+
if emptyHandler != nil {
37+
previousIsEmpty = self.snapshot().isEmpty
38+
}
3539
switch option {
3640
case .usingReloadData:
3741
if #available(iOS 15.0, tvOS 15.0, *) {
@@ -56,6 +60,6 @@ public extension UICollectionViewDiffableDataSource {
5660
}
5761
}
5862
}
59-
updateEmptyView()
63+
updateEmptyView(snapshot, previousIsEmpty: previousIsEmpty)
6064
}
6165
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// NSDiffableDataSourceSnapshot+.swift
3+
//
4+
//
5+
// Created by Florian Zand on 22.02.24.
6+
//
7+
8+
import UIKit
9+
10+
extension NSDiffableDataSourceSnapshot {
11+
/// A Boolean value indicating whether the snapshot is empty.
12+
var isEmpty: Bool {
13+
numberOfItems == 0 && numberOfSections == 0
14+
}
15+
}

Sources/AdvancedCollectionTableView-iOS/TableView/DataSource/TableViewDiffableDataSource.swift

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class TableViewDiffableDataSource<SectionIdentifierType, ItemIdentifierType> : U
4747
oldValue?.removeFromSuperview()
4848
if emptyView != nil {
4949
emptyContentConfiguration = nil
50-
updateEmptyView()
50+
updateEmptyView(snapshot())
5151
}
5252
}
5353
}
@@ -66,37 +66,63 @@ class TableViewDiffableDataSource<SectionIdentifierType, ItemIdentifierType> : U
6666
} else {
6767
emptyContentView = .init(configuration: configuration)
6868
}
69-
updateEmptyView()
69+
updateEmptyView(snapshot())
7070
} else {
7171
emptyContentView?.removeFromSuperview()
7272
emptyContentView = nil
7373
}
7474
}
7575
}
7676

77+
/**
78+
The handler that gets called when the data source is switching between an empty and non-empty snapshot or viceversa.
79+
80+
You can use this handler e.g. if you want to update your empty view or content configuration.
81+
*/
82+
open var emptyHandler: ((_ isEmpty: Bool)->())? {
83+
didSet {
84+
if let emptyHandler = self.emptyHandler {
85+
emptyHandler(snapshot().isEmpty)
86+
}
87+
}
88+
}
89+
7790
var emptyContentView: ContentConfigurationView?
7891

7992
override func apply(_ snapshot: NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>, animatingDifferences: Bool = true, completion: (() -> Void)? = nil) {
93+
var previousIsEmpty: Bool?
94+
if emptyHandler != nil {
95+
previousIsEmpty = self.snapshot().isEmpty
96+
}
8097
super.apply(snapshot, animatingDifferences: animatingDifferences, completion: completion)
81-
updateEmptyView()
98+
updateEmptyView(snapshot, previousIsEmpty: previousIsEmpty)
8299
}
83100

84101
@available(iOS 15.0, tvOS 15.0, *)
85102
override func applySnapshotUsingReloadData(_ snapshot: NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>, completion: (() -> Void)? = nil) {
103+
var previousIsEmpty: Bool?
104+
if emptyHandler != nil {
105+
previousIsEmpty = self.snapshot().isEmpty
106+
}
86107
super.applySnapshotUsingReloadData(snapshot, completion: completion)
87-
updateEmptyView()
108+
updateEmptyView(snapshot, previousIsEmpty: previousIsEmpty)
88109
}
89110

90-
func updateEmptyView() {
91-
let snapshot = snapshot()
92-
if !snapshot.itemIdentifiers.isEmpty && !snapshot.sectionIdentifiers.isEmpty {
111+
func updateEmptyView(_ snapshot: NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>, previousIsEmpty: Bool? = nil) {
112+
if !snapshot.isEmpty {
93113
emptyView?.removeFromSuperview()
94114
emptyContentView?.removeFromSuperview()
95115
} else if let emptyView = self.emptyView, emptyView.superview != tableView {
96116
tableView?.addSubview(withConstraint: emptyView)
97117
} else if let emptyContentView = self.emptyContentView, emptyContentView.superview != tableView {
98118
tableView?.addSubview(withConstraint: emptyContentView)
99119
}
120+
if let emptyHandler = self.emptyHandler, let previousIsEmpty = previousIsEmpty {
121+
let isEmpty = snapshot.isEmpty
122+
if previousIsEmpty != isEmpty {
123+
emptyHandler(isEmpty)
124+
}
125+
}
100126
}
101127

102128
/// The handlers for selecting rows.

0 commit comments

Comments
 (0)