Infinite Scrolling List for Paginated Results from GraphQL with SwiftUI
Tackling
AttributeGraph precondition failure: setting value during update
using Realm in SwiftUIInfinite Scrolling List for Paginated Results from GraphQL with SwiftUI
Open Third-Party URLs in a SwiftUI App Using a Share Extension
Synced Realm on iOS with SwiftUI using Sign-in with Apple for Authentication
Creating a list in SwiftUI is pretty simple using List
. While hard-coded lists do not necessarily contain many items, we usually refer to other data sources, e.g., an API, to populate lists. This way, the items in the list can easily exceed the available vertical display space which automatically makes the list scrollable. However, the API used as the list’s data source may not return all items that satisfy the corresponding request. Rather, the returned results are paginated where only one of the pages is returned at a time. To enable the user to scroll through the list of all items seamlessly, we refer to the paradigm of infinite scrolling which is not provided by SwiftUI’s List
, though.
GraphQL
Compared to REST, GraphQL is a typed, version-less language to query an API. The language’s specification does not define pagination but denotes the paradigm as a best practice. It is up to the API provider to decide whether they want to implement pagination in their API. For example, GitLab’s GraphQL API implements GraphQL’s recommendation and returns 100 items per page by default. For Swift, there are different libraries to implement GraphQL on the server- and client-side. In our example, we will use the client-side library Apollo iOS to query paginated results from an API as the data source for a List
.
Implementation
GitLab is a DevOps platform that supports teams from planning to production in software development. With so-called issues, the platform offers a way "to collaborate on ideas, solve problems, and plan work". To retrieve these issues outside of GitLab, a REST and GraphQL API are available. Our goal is to use the GraphQL API to retrieve the issues of a project and display them as a List
in SwiftUI using infinite scrolling. Before diving into our example, we have to install Apollo iOS. As detailed in Apollo’s documentation, we download the schema of GitLab’s GraphQL API, create a client, and set up a query to perform for our List
.
View Model
After this, we arrive at the following view model that populates issues
with paginated results from GitLab’s API:
In particular, loadIssuesIfAny
verifies whether any issues have been loaded already. If so, the function makes sure that next page of issues is loaded. In both cases, loadIssuesIfAny
refers to loadIssues
to retrieve the corresponding page from the API using a cursor
. loadIssues
uses the ProjectIssuesQuery
which includes the information necessary to navigate the pagination:
View
Using the view model, we can create the corresponding view with an infinite scrolling List
:
As with a finite scrolling list, the infinite scrolling variant contains a ForEach
that renders the currently loaded pages. In addition, the List
also contains a ProgressView
that serves as a loading indicator during the retrieval of additional pages. This loading indicator is visible as soon as viewModel.isLoadingMore
is true
. That is the case after the user reaches the end of the list and the last item of the currently loaded page appears. onAppear
then calls loadIssuesIfAny
to retrieve the next page of issues if any.
Demonstration
Below we can see the result of the above implementation running on iOS 15:
Please note that this implementation contains more features than described above and looks slightly different as a consequence. That does not affect the presentation of the infinite scrolling paradigm, though.