How to Create Infinite Scroll in UITableView

Simple way to paginate your TableView based on API data

Mohd Hafiz
Level Up Coding

--

Image by Author

Overview

The rise of social media platforms such as Facebook and Twitter have had a significant impact on the world today. People appear to have a habit of scrolling through their feeds all day, looking at various information and stories.

A feed page is a common feature in every social app that allows users to scroll indefinitely. In this article, we will learn how to fetch large amounts of data with pagination. We will be using GitHub API to simulate the endless data request.

GitHub provides an API in which some of the endpoints are public and the data can be accessed without requiring authentication, such as getting a list of users and public repositories.

What Will We Build?

We are going to create a simple app that has the following capabilities.

1. Able to call API and scroll UITableView with pagination.

We will use Github API to get a list of users. It contains all GitHub users since the beginning it was founded.

Load API data with pagination

In the result above, I used the Network Conditioner tool to create an “Edge” connection so that we can see the loading process (a High-speed network will be very fast and seamless loading).

2. Handle request error

I then changed to “100% Loss” to show error handling on failed data fetches. See my previous article on how to simulate multiple network conditions.

UI handling on network failure

Coding Begins

1. Create New UIKit Project

In this project, we will use UIKit and Storyboard.

2. Insert Navigation Controller (Optional)

After creating the project, embed the default ViewController with Navigation View Controller. Select Main.storyboard, then select the top menu Editor > Embed in > Navigation Controller.

3. Insert UITableView to Storyboard

Open the storyboard and insert UITableView. Then pin the constraint to the edges of superview. Don’t forget to link the UITableView as an IBOutlet in ViewController class.

4. Create User Model

Create a new model file called User.swift and add this code. We only get the id, name, and avatarUrl from the JSON object. In this project, we will only display the name as for a quick example.

5. Create API Service Manager

/users endpoint details from GitHub API docs

Create a new file called “GithubAPIManager.swift” to handle API requests. It is just a common API request using URLSession with dataTask() method. In that file, insert the below code.

  1. Create an error type to be used in the completion handler
  2. Construct proper API URL with parameters
  3. Create URLRequest with a timeout of 10 seconds.

5. Setup TableView and API Integration

Open your ViewController file and add the below code. Also at the bottom of code, we add some of the TableView datasource methods (delegate methods will be used in the next step).

  1. Add users variable to store data from API and whenever it is set, TableView will immediately reload its content.
  2. setupView(), a simple setup on TableView. We need to add .delegate later.
  3. A function to call our API service and handle data received.
  4. Add a default TableView Cell to display the name and row number.

After adding the code, run your project and you should get the simple TableView list as shown in the below image. You will get exactly 30 rows in the TableView as the default perPage parameter and not yet able to paginate.

Simple TableView list with static data of 30 users

6. Setup Pagination

Great. We are done setting up the base of the project. Now, we need to make some updates to make sure our user list can be scrolled endlessly. Update our ViewController class as follows and see the explanation of each code change.

The following is the explanation of the amendments.

  1. We added new enum of TableSection. Our TableView will have two sections. The first is to keep the same user list while the second one is to keep the loader cell.
  2. Two more variables are added. pageLimit is used to keep the constant of limit objects requested and currentLastId is used to store id of the last User object in the users array. The currentLastId will be used when fetching the next page API by providing the since parameter with the last id that we already fetched.
  3. Assign TableView delegate to current ViewController to enable use of willDisplay method call.
  4. Update fetchData with completion callback to receive the success or failure status.
  5. Change = to .append method to keep the users array expanding instead of replacing.
  6. Update completion() with success status.
  7. Added numberOfSections since we will keep two section, as mentioned in point number 1.
  8. numberOfRowsInSection is now depending on the section. Also, only if the users data size is more pageLimit, then we will show the loading cell.
  9. Simply update cell text to name for user list and “Loading.. ” for the second section.
  10. This is the important part where the loader cell will appear and the API service will start fetching new data (next page).
  11. In the previous point, in the willDisplay method, the hideBottomLoader() will be called when the error happens. Yeah, we are done! Try to run the code and keep scrolling to the bottom until you reach your name 😆.

Potential Bug

There is a potential bug that might happen when the network connection is slow. When users reach the bottom loader cell, they may continue to scroll up and down in order to send multiple API requests with the same currentLastId. As a result, the success data will be redundant.

It’s you homework to fix this issue 🤭

Don’t panic! The simplest solution is to compare the currentLastId each time the request is sent. Make sure to check the currentLastId is different from the previous requests. Yes, that’s it.

Project Completed

Congratulations! We have completed all of the steps and the project is now ready and works perfectly. The entire source code is available for download from my GitHub repository. You may try implementing it into your projects and perhaps improving the code by developing a subclass or UITableView extension, so that it can be reused in other view controllers.

Thanks for reading. Happy coding!

--

--

iOS Developer focusing on Swift — “Read, learn & practice!”.