Skip to content

Commit 2d9450f

Browse files
BBTableView adds pullUpToLoadMore
1 parent 47eb675 commit 2d9450f

File tree

2 files changed

+39
-13
lines changed

2 files changed

+39
-13
lines changed

BBSwiftUIKit/BBSwiftUIKit/BBTableView.swift

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88

99
import SwiftUI
1010

11+
public extension CGFloat {
12+
static let bb_invalidBottomSpaceForLoadingMore = CGFloat.greatestFiniteMagnitude
13+
}
14+
1115
public extension BBTableView {
1216
func bb_reloadData(_ reloadData: Binding<Bool>) -> Self {
1317
var view = self
@@ -45,12 +49,19 @@ public extension BBTableView {
4549
return view
4650
}
4751

48-
func bb_pullDownToRefresh(_ isRefreshing: Binding<Bool>, refresh: @escaping () -> Void) -> Self {
52+
func bb_pullDownToRefresh(isRefreshing: Binding<Bool>, refresh: @escaping () -> Void) -> Self {
4953
var view = self
5054
view._isRefreshing = isRefreshing
5155
view.pullDownToRefresh = refresh
5256
return view
5357
}
58+
59+
func bb_pullUpToLoadMore(bottomSpace: CGFloat, loadMore: @escaping () -> Void) -> Self {
60+
var view = self
61+
view.bottomSpaceForLoadingMore = bottomSpace
62+
view.pullUpToLoadMore = loadMore
63+
return view
64+
}
5465
}
5566

5667
public struct BBTableViewScrollToRowParameter {
@@ -84,6 +95,8 @@ public struct BBTableView<Data, Content>: UIViewControllerRepresentable, BBUIScr
8495
@Binding public var isRefreshing: Bool
8596
public var setupRefreshControl: ((UIRefreshControl) -> Void)?
8697
public var pullDownToRefresh: (() -> Void)?
98+
public var bottomSpaceForLoadingMore: CGFloat
99+
public var pullUpToLoadMore: (() -> Void)?
87100

88101
public init(_ data: Data,
89102
reloadData: Binding<Bool> = .constant(false),
@@ -100,6 +113,8 @@ public struct BBTableView<Data, Content>: UIViewControllerRepresentable, BBUIScr
100113
isRefreshing: Binding<Bool> = .constant(false),
101114
setupRefreshControl: ((UIRefreshControl) -> Void)? = nil,
102115
pullDownToRefresh: (() -> Void)? = nil,
116+
bottomSpaceForLoadingMore: CGFloat = .bb_invalidBottomSpaceForLoadingMore,
117+
pullUpToLoadMore: (() -> Void)? = nil,
103118
@ViewBuilder content: @escaping (Data.Element) -> Content)
104119
{
105120
self.data = data
@@ -118,6 +133,8 @@ public struct BBTableView<Data, Content>: UIViewControllerRepresentable, BBUIScr
118133
self._isRefreshing = isRefreshing
119134
self.setupRefreshControl = setupRefreshControl
120135
self.pullDownToRefresh = pullDownToRefresh
136+
self.bottomSpaceForLoadingMore = bottomSpaceForLoadingMore
137+
self.pullUpToLoadMore = pullUpToLoadMore
121138
}
122139

123140
public func makeUIViewController(context: Context) -> UIViewController {
@@ -165,7 +182,7 @@ private class _BBTableViewController<Data, Content>: UIViewController, UITableVi
165182
tableView.refreshControl = refreshControl
166183
}
167184

168-
// TODO: Detect content offset to bottom space and load more data
185+
// TODO: Refresh when first will appear
169186

170187
NSLayoutConstraint.activate([
171188
view.leftAnchor.constraint(equalTo: tableView.leftAnchor),
@@ -264,6 +281,14 @@ private class _BBTableViewController<Data, Content>: UIViewController, UITableVi
264281
DispatchQueue.main.async { [weak self] in
265282
guard let self = self else { return }
266283
self.representable.contentOffset = scrollView.contentOffset
284+
285+
if self.representable.bottomSpaceForLoadingMore != .bb_invalidBottomSpaceForLoadingMore,
286+
let loadMore = self.representable.pullUpToLoadMore {
287+
let space = scrollView.contentSize.height - scrollView.contentOffset.y - scrollView.frame.height
288+
if space <= self.representable.bottomSpaceForLoadingMore {
289+
loadMore()
290+
}
291+
}
267292
}
268293
}
269294
}

BBSwiftUIKitDemo/BBSwiftUIKitDemo/TableViewExample.swift

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ struct TableViewExample: View {
1818
@State var contentOffset: CGPoint = .zero
1919
@State var contentOffsetToScrollAnimated: CGPoint? = nil
2020
@State var isRefreshing: Bool = false
21+
@State var isLoadingMore: Bool = false
2122

2223
var body: some View {
2324
VStack {
@@ -45,12 +46,20 @@ struct TableViewExample: View {
4546
refreshControl.tintColor = .blue
4647
refreshControl.attributedTitle = NSAttributedString(string: "Loading...", attributes: [.font: UIFont.systemFont(ofSize: 15), .foregroundColor: UIColor.blue])
4748
}
48-
.bb_pullDownToRefresh($isRefreshing) {
49+
.bb_pullDownToRefresh(isRefreshing: $isRefreshing) {
4950
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
5051
self.reloadListData()
5152
self.isRefreshing = false
5253
}
5354
}
55+
.bb_pullUpToLoadMore(bottomSpace: 30) {
56+
if self.isLoadingMore { return }
57+
self.isLoadingMore = true
58+
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
59+
self.list = 0..<self.list.last! + 11
60+
self.isLoadingMore = false
61+
}
62+
}
5463

5564
Slider(value: $contentOffset.y, in: 0...1000)
5665

@@ -74,21 +83,13 @@ struct TableViewExample: View {
7483
}
7584

7685
private func reloadListData() {
77-
if self.list.count > 50 {
78-
self.list = 0..<50
79-
} else {
80-
self.list = 0..<100
81-
}
86+
self.list = 0..<100
8287
self.updateHeight.toggle()
8388
self.reloadData = true
8489
}
8590

8691
private func reloadListRows() {
87-
if self.list.count > 50 {
88-
self.list = 0..<50
89-
} else {
90-
self.list = 0..<100
91-
}
92+
self.list = 0..<100
9293
self.updateHeight.toggle()
9394
self.reloadRows = (0..<10).map { $0 }
9495
}

0 commit comments

Comments
 (0)