Easy Pagination in SwiftUI

Simple and robust implementation of infinite scrolling in SwiftUI

Yugantar Jain
The Startup
3 min readJul 21, 2020

--

Background by Víctor Elvira Ávalos on Unsplash. SwiftUI logo by Apple.

Hi everyone,

In this article, I’ll be sharing a simple and robust method to implement an infinitely scrolling list in SwiftUI with the help of Combine.

Pagination and the role of an infinitely scrolling list

Pagination is a technique that is implemented in backend APIs to save network load by returning only a small number of records divided in a page-wise manner.

For example, suppose an API returns the list of users of a system, there can be hundreds of thousands of users. Loading all the users at once won’t only make the network call incredibly slow, but will also waste data of the user. Hence, the industry standard is to return parts of the data in a page-wise manner.

Since a paginated backend API doesn’t return all the data at once, it has to be implemented in the frontend as well (usually as an infinite scrolling list).

Eg. Instagram uses an infinitely scrolling list to load more posts from the server only when the user scrolls to the bottom (end of list).

Note: I have used ‘Pagination’ and ‘Infinite Scrolling ’ interchangeably in this article.

While ‘Pagination’ is the core concept, ‘Infinite Scrolling’ is the common frontend implementation of it.

Implementation in SwiftUI

In our article, to implement pagination in the app we’ll be using —

  1. Xcode 11 and SwiftUI — for the development of our app. Hence, iOS 13 is also supported.
  2. Combine — for observable model class and to make network requests to the backend API that supports pagination.

Let’s get started!

1. Infinite Scrolling List, SwiftUI View

Our infinite scrolling list view comprises of a List inside a Navigation View.

The List is composed of two parts —

  1. The Members. This part shows the loaded members using a ForEach loop. Whenever we load new members from the backend, this part grows.
  2. The Activity Indicator. This is always the last cell of the list. It is only shown if there are more members available to be loaded.

Note: MemberListCell and ActivityIndicator are custom views.

On line 19, we have used the onAppear modifier on the activity indicator (implies the user has reached the end of the list) to load more members.

Since the spinner is only shown if more members are available to be loaded, its onAppear method is also called and makes a network request only when required. Perfect!

2. MemberData model class + Combine

Our infinite scrolling list view uses an object of the MemberData class. This class is responsible to provide the data to the view and load data from the backend.

The ‘members’ property is published, hence, the view updates automatically when it changes (i.e. list grows seamlessly in the View).

Combine has built-in cancellation, and this is incredibly powerful. As I have previously explained in this post, AnyCancellable (line 15, 18) automatically cancels the subscription at suitable times. Hence, Combine makes sure that we do not duplicate network requests, by automatically cancelling them whenever required.

This ensures that if the user scrolls and hides/shows the activity spinner multiple times, we do not make unnecessary network calls and our list data doesn’t get corrupted with duplicate/wrong data. It all works perfectly!

We’re done! Pagination has been implemented :)

Infinite Scrolling in Mentorship iOS app

Conclusion

We’ve successfully implemented infinite scrolling in SwiftUI for a pagination enabled backend API.

< It looks something like this

The Combine framework plays a vital role in the development of SwiftUI apps, usually to make model classes observable.

We’ve also used Combine to make network calls in conjunction with URLSession, and have taken advantage of its built-in cancellation (AnyCancellable) to keep the user experience seamless and error-free.

The internet is filled with a lot of complex methods to implement infinite scrolling in SwiftUI (especially for Xcode 11).

I would like to thank my GSoC20 Mentor, Vatsal, for telling me about this neat, simple, and robust method to implement it.

Thank You for Reading!

Please feel free to reach out to me and connect, check out our projects, or join our open source community:
LinkedIn, GitHub, Mentorship iOS, AnitaB.org Community

--

--