Swift iOS Add Infinite Scroll Pagination to Uitableview

Infinite scrolling pagination of the TableView

You can see that you have reached the bottom of the list with willDisplay function from the UITableViewDelegate protocol. like below code:

public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forItemAt indexPath: IndexPath) {
let lastIndex = self.popularMoviesArray.count - 1
if indexPath.row == lastIndex {
// api call and get next page
}
}

and you can call API to get the next page data.
then append new data to your data source list and reload tableView:

self.popularMoviesArray.append(contentsOf: newListData)
self.tableView.reloadData()

Infinite scroll tableView, swift

Add completion handler in loadMoreData() method & use a boolean check for call like below -

var isLoadingStarted = true

func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
let contentHeight = scrollView.contentSize.height

if offsetY > contentHeight - scrollView.frame.height {

if vievModel.!paginationFinished && isLoadingStarted {
isLoadingStarted = false
self.viewModel.loadMoreData {
self.tableView.reloadData()
//self.isLoadingStarted = true
}

}
}
}

//Handle loadMoreData method as below
static func loadMoreData(_ , completion:@escaping (() -> Void)) {
.
.
.
completion()

}

Use scroll view delegate to detect begin dragging and set flag isLoadingStarted there -

func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
self.isLoadingStarted = true
}

Try it once.

UITableView infinite scrolling

If you need to know when you hit the bottom of the UITableView, become it's delegate (because it is a subclass of UIScrollView), and use the -scrollViewDidScroll: delegate method to compare the table's content height and it's actual scroll position.

EDIT (something like this):

- (void)scrollViewDidScroll:(UIScrollView *)scrollView_ 
{
CGFloat actualPosition = scrollView_.contentOffset.y;
CGFloat contentHeight = scrollView_.contentSize.height - (someArbitraryNumber);
if (actualPosition >= contentHeight) {
[self.newsFeedData_ addObjectsFromArray:self.newsFeedData_];
[self.tableView reloadData];
}
}

Swift tableView Pagination

For that you need to have server side change also.

  1. Server will accept fromIndex and batchSize in the API url as query param.

    let listUrlString =  "http://bla.com/json2.php?listType=" + listType + "&t=" + NSUUID().UUIDString + "&batchSize=" + batchSize + "&fromIndex=" + fromIndex
  2. In the server response, there will be an extra key totalItems. This will be used to identify all items are received or not. An array or items fromIndex to batchSize number of items.

In the app side

  1. First loadItem() will be called with fromIndex = 0 and batchSize = 20 (for example in viewDidLoad() or viewWillAppear). removeAll items from privateList array before calling loadItem() for the first time

  2. Server returns an array of first 20 items and totalItems total number of items in the server.

  3. Append the 20 items in privateList array and reload tableView

  4. In tableView:cellForRowAtIndexPath method check if the cell is the last cell. And check if totalItems (form server) is greater than privateList.count. That means there are more items in the server to load

    if indexPath.row == privateList.count - 1 { // last cell
    if totalItems > privateList.count { // more items to fetch
    loadItem() // increment `fromIndex` by 20 before server call
    }
    }

Question: where is refresh ? will be scrolling ?

Refresh after appending new items in the array when server response received. (step 3)

Scrolling will trigger tableView:cellForRowAtIndexPath for every cell when user scrolls. Code is checking if it is the last cell and fetch remaining items. (step 4)

Sample project added:
https://github.com/rishi420/TableViewPaging



Related Topics



Leave a reply



Submit