Skip to content

Instantly share code, notes, and snippets.

@YoomamaFTW
Last active November 13, 2019 01:30
Show Gist options
  • Save YoomamaFTW/0d200786dc5bd8eb5badfac2c6924666 to your computer and use it in GitHub Desktop.
Save YoomamaFTW/0d200786dc5bd8eb5badfac2c6924666 to your computer and use it in GitHub Desktop.
Problem with table loading cells after they come into view.
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var tableView: UITableView!
private var fetchingMore = false
var delay: Double!
var items = [[Any]]()
override func viewDidLoad() {
super.viewDidLoad()
tableView = UITableView(frame: view.bounds, style: .plain)
tableView.delegate = self
tableView.dataSource = self
tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "custom")
let loadingNib = UINib(nibName: "LoadingCell", bundle: nil)
tableView.register(loadingNib, forCellReuseIdentifier: "loadingCell")
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
let layoutGuide = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
tableView.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor),
tableView.topAnchor.constraint(equalTo: layoutGuide.topAnchor),
tableView.trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor),
tableView.bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor)
])
tableView.reloadData()
}
open func addNewComponent() {
var blah = [[Any]]()
for x in 0...12 {
blah.append([1, self.randomString(length: 250)])
}
self.items.append(contentsOf: blah)
}
open func addNewCell(components: Array<Any>, path: IndexPath) -> UITableViewCell { return UITableViewCell() }
func tempAddNewCell(components: Array<Any>, path: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "custom", for: path) as? CustomTableViewCell
cell?.labMessage.text = "MessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessageMessage"
cell?.labTime.text = "\(path) h"
cell?.labUerName.text = "Username"
return cell!
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let components = items[indexPath.row]
return tempAddNewCell(components: components, path: indexPath)
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "loadingCell", for: indexPath) as! LoadingCell
cell.spinner.startAnimating()
return cell
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return items.count
} else if section == 1 && fetchingMore {
return 1
}
return 0
}
func numberOfSections(in tableView: UITableView) -> Int { return 2 }
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
let contentHeight = scrollView.contentSize.height
if offsetY > contentHeight - scrollView.frame.height * 2 {
if !fetchingMore { beginBatchFetch() }
}
}
func beginBatchFetch() {
fetchingMore = true
tableView.reloadSections(IndexSet(integer: 1), with: .none)
DispatchQueue.main.asyncAfter(deadline: .now() + (self.delay ?? 0.1), execute: {
self.addNewComponent()
self.fetchingMore = false
self.tableView.reloadData()
})
}
}
class CustomTableViewCell: UITableViewCell {
let imgUser = UIImageView()
let labUerName = UILabel()
let labMessage = UILabel()
let labTime = UILabel()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
imgUser.backgroundColor = UIColor.blue
imgUser.translatesAutoresizingMaskIntoConstraints = false
labUerName.translatesAutoresizingMaskIntoConstraints = false
labMessage.translatesAutoresizingMaskIntoConstraints = false
labTime.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(imgUser)
contentView.addSubview(labUerName)
contentView.addSubview(labMessage)
contentView.addSubview(labTime)
let viewsDict = [
"image" : imgUser,
"username" : labUerName,
"message" : labMessage,
"labTime" : labTime,
] as [String : Any]
contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[image(10)]", options: [], metrics: nil, views: viewsDict))
contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[labTime]-|", options: [], metrics: nil, views: viewsDict))
contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[username]-[message]-|", options: [], metrics: nil, views: viewsDict))
contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[username]-[image(10)]-|", options: [], metrics: nil, views: viewsDict))
contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[message]-[labTime]-|", options: [], metrics: nil, views: viewsDict))
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
@YoomamaFTW
Copy link
Author

Used this tutorial: https://github.com/RobCanton/Swift-Infinite-Scrolling-Example/tree/master/InfiniteScrollingExample-End

I made a bunch of tweaks such as inserting certain cells; ended up deleting them for this gist to keep concise... a little. When I use the tutorial's ViewController, the infinite table works seamlessly. When you run the above code, you'll see that the table's view jumps up then back down. I think I've deduced it down to the point of the "beginBatchFetch()" func being the problem.

When viewing the problem, it caught my attention that the appending items and then the insertion of cells in correspondence to those items happened at different times. The appending of items happens at the exact time but the insertion of cells happens when the table is barely in view of the bottom.

Can someone help out?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment