I have a tableView and json data.I want tableview load half in json data. When table view scroll comes to the end of the first half , the other half will be load.Can anyone know how I can ?
CodePudding user response:
I believe you will have to do some pagination
type of processing on your side with the help of scrollViewDidScroll
to observe when you reach the end of a the tableview to load the next batch
Start by setting some initial variables to help you track the paging process.
var pageStart = 0
var pageSize = 15
// scrollViewDidScroll will be called several times
// so we need to be able to block the loading process
var isLoadingItems = false
// Array of 50 values which you get from the API
// For example your JSON data
var totalNumberOfItems = (0...49).reduce([Int]())
{ (result, number) in
var array = result
array.append(number)
return array
}
// This will periodically be filled with items from totalNumberOfItems
var itemsToLoad: [Int] = []
I create this loading function which helps with adding the items in batches and reloading the tableview appropriately
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
loadItems()
}
private func loadItems(withDelay delay: Double = 0) {
// Check that there are items to load
if pageStart < totalNumberOfItems.count, !isLoadingItems {
isLoadingItems = true
// The delay and dispatch queue is just to show you the
// loading of data in batches, it is not needed for the
// solution
if delay > 0 {
presentLoader()
}
DispatchQueue.main.asyncAfter(deadline: .now() delay) {
if delay > 0 {
// dismiss the loader
self.dismiss(animated: true, completion: nil)
}
// Calculate the page end based on the page size or on
// the number of items remaining to load if the page size
// is greater than the number of items remaining
var pageEnd = self.pageStart self.pageSize - 1
if pageEnd > self.totalNumberOfItems.count {
let remainingItems = self.totalNumberOfItems.count - self.pageStart - 1
pageEnd = self.pageStart remainingItems
}
let newItems = Array(self.totalNumberOfItems[self.pageStart ... pageEnd])
self.itemsToLoad.append(contentsOf: newItems)
self.pageStart = pageEnd 1
let indexPaths = newItems.map { IndexPath(row: $0,
section: 0) }
// Update the table view
self.tableView.beginUpdates()
self.tableView.insertRows(at: indexPaths, with: .fade)
self.tableView.endUpdates()
// scroll to first newly inserted row
if let firstNewRow = indexPaths.first {
self.tableView.scrollToRow(at: firstNewRow,
at: .top,
animated: true)
}
// Unlock the loading process
self.isLoadingItems = false
}
}
}
Then observe if you reached the end using scrollViewDidScroll
and reload the tableview to show the inserted rows
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
// Check that the current scroll offset is > 0 so you don't get
// any false positives when the table view is set up
// and check if the current offset has reached the end
if scrollView.contentOffset.y >= 0 &&
scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height) {
print("reached end, load more")
// Load more data
loadItems(withDelay: 1)
}
}
Here is how that will look:
If you found some part difficult to follow or add into your own code, the complete code which can run as is can be found here: