UITableView can support scrolling through many rows of data, however fetching large amounts of remote data can slow down your app, use up too much memory, and bog down your web server. This is all wasteful if users aren‘t ever going to scroll down that far. In this episode you‘ll learn how to perform automatic UITableView pagination using an easy technique.
This episode is a refresh of Episode 8. Setting Up private var beers: [Beer] = [] private var currentPage = 1 private var shouldShowLoadingCell = false override func viewDidLoad() { // ... refreshControl = UIRefreshControl() refreshControl?.addTarget(self, action: #selector(refreshBeers), for: .valueChanged) refreshControl?.beginRefreshing() loadBeers() } Loading the Data private func loadBeers(refresh: Bool = false) { print("Fetching page \(currentPage)") breweryDBClient.fetchBeers(page: currentPage, styleId: 3) { page in DispatchQueue.main.async { if refresh { self.beers = page.data } else { for beer in page.data { if !self.beers.contains(beer) { self.beers.append(beer) } } } self.shouldShowLoadingCell = page.currentPage < page.numberOfPages self.refreshControl?.endRefreshing() self.tableView.reloadData() } } } Fetching the next page private func fetchNextPage() { currentPage += 1 loadBeers() } Showing the Loading Cell If we need to show a loading cell we need to add 1 to the cell count: override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { let count = beers.count return shouldShowLoadingCell ? count + 1 : count } Then return a cell for the loading index path: private func isLoadingIndexPath(_ indexPath: IndexPath) -> Bool { guard shouldShowLoadingCell else { return false } return indexPath.row == self.beers.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { if isLoadingIndexPath(indexPath) { return LoadingCell(style: .default, reuseIdentifier: "loading") } else { //... } } Then we need to trigger the next page load when the cell is displayed... override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { guard isLoadingIndexPath(indexPath) else { return } fetchNextPage() } Refreshing the Data @objc private func refreshBeers() { currentPage = 1 loadBeers(refresh: true) }