Skip to content

Instantly share code, notes, and snippets.

@0xLeif
Created January 17, 2020 23:20
Show Gist options
  • Save 0xLeif/cf6da14282dee2c1127d2ffa54fab18d to your computer and use it in GitHub Desktop.
Save 0xLeif/cf6da14282dee2c1127d2ffa54fab18d to your computer and use it in GitHub Desktop.
LazyTable
class LazyTable: UITableView {
fileprivate var loadThreshold: CGFloat = 0.75 // 75%
fileprivate var loadAmount: Int = 25
fileprivate var loadCount: Int = 1
fileprivate var batchCount: Int {
return loadAmount * loadCount
}
fileprivate var elements: [UIView] = [] {
didSet {
if loadAmount > elements.count {
reloadData()
}
}
}
private var configureCell: ((UITableViewCell) -> Void)?
init(style: UITableView.Style = .plain) {
super.init(frame: .zero, style: style)
delegate = self
dataSource = self
// TODO: Params
estimatedRowHeight = 100
// rowHeight = 120
register(UITableViewCell.self, forCellReuseIdentifier: "cell")
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func reload() {
if elements.count >= batchCount {
loadCount += 1
print("Load Count: \(loadCount)")
}
reloadData()
}
}
extension LazyTable: UITableViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard scrollView.contentOffset.y > 0 else {
return
}
let percentToBottom = scrollView.contentOffset.y / scrollView.contentSize.height
print("Offset: \(scrollView.contentOffset)")
print("Height: \(scrollView.contentSize.height)")
print("Percent: \(percentToBottom * 100)%")
if percentToBottom >= loadThreshold {
reload()
}
}
}
extension LazyTable: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard batchCount < elements.count else {
print("Loading Elements: \(elements.count)")
return elements.count + 1
}
print("Loading Batch: \(batchCount)")
return batchCount + 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
guard indexPath.row != elements.count else {
cell.contentView.clear()
.embed {
VStack {
[
LoadingView()
.configure { $0.color = .blue }
.start()
]
}
}
return cell
}
configureCell?(cell)
cell.contentView.clear().embed {
elements[indexPath.row]
}
return cell
}
}
extension LazyTable {
func add(_ elements: () -> [UIView]) -> Self {
self.elements += elements()
return self
}
func configureCell(_ action: @escaping (UITableViewCell) -> Void) -> Self {
self.configureCell = action
return self
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment