Enum-Driven TableView Development

In this tutorial, you will learn how to use Swift enums to handle the different states of your app to populate a table view. By Keegan Rush.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

Setting the State to .paging

In update(response:), replace state = .populated(newRecordings) with this:

if response.hasMorePages {
  state = .paging(newRecordings, next: response.nextPage)
} else {
  state = .populated(newRecordings)
}

response.hasMorePages tells you if the total number of pages that the API has for the current query is less than the current page. If there are more pages to be fetched, you set the state to .paging. If the current page is the last page or the only page, then set the state to .populated.

Build and run the app:

Pagination with loading state

If you search for something with multiple pages, the app displays the loading indicator at the bottom. But if you search for a term that has only one page of results, you would get the usual .populated state without the loading indicator.

You can see when there are more pages to be loaded, but the app isn’t doing anything to load them. You’ll fix that now.

Loading the Next Page

When the user is about to reach the end of the list, you want the app to start loading the next page. First, create a new empty method named loadPage:

func loadPage(_ page: Int) {
}

This is the method that you’ll call when you want to load a particular page of results from the NetworkingService.

Remember how loadRecordings() was loading the first page by default? Move all the code from loadRecordings() to loadPage(_:), except for the first line where the state is set to .loading.

Next, update fetchRecordings(matching: query, page: 1) to use the page parameter, like this:

networkingService.fetchRecordings(matching: query, page: page)

loadRecordings() is looking a little bare now. Update it to call loadPage(_:), specifying page 1 as the page to be loaded:

@objc func loadRecordings() {
  state = .loading
  loadPage(1)
}

Build and run the app:

If nothing has changed, you’re on the right track!

Add the following to tableView(_: cellForRowAt:), just before the return statement.

if case .paging(_, let nextPage) = state,
  indexPath.row == state.currentRecordings.count - 1 {
  loadPage(nextPage)
}

If the current state is .paging, and the current row to be displayed is the same index as the last result in the currentRecordings array, it’s time to load the next page.

Build and run the app:

Exciting! When the loading indicator comes into view, the app fetches the next page of data. But it doesn’t append the data to the current recordings — it just replaces the current recordings with the new ones.

Appending the Recordings

In update(response:), the newRecordings array is being used for the view’s new state. Before the if response.hasMorePages statement, add this:

var allRecordings = state.currentRecordings
allRecordings.append(contentsOf: newRecordings)

You get the current recordings and then append to new recordings to that array. Now, update the if response.hasMorePages statement to use allRecordings instead of newRecordings:

if response.hasMorePages {
  state = .paging(allRecordings, next: response.nextPage)
} else {
  state = .populated(allRecordings)
}

See, how easy was it with the help of the state enum? Build and run the app to see the difference:

Search with working pagination

Where to Go From Here?

If you want to download the finished project, use the Download Materials button at the top or bottom of this tutorial.

In this tutorial, you refactored an app to handle complexity in a much clearer way. You replaced a lot of error-prone, poorly defined state with a clean and simple Swift enum. You even tested out your enum-driven table view by adding a complicated new feature: pagination.

When you refactor code, it’s important to test things to make sure that you haven’t broken anything. Unit tests are great for this. Take a look at the iOS Unit Testing and UI Testing tutorial to learn more.

Now that you’ve learned how to work with a pagination API in an app, you can learn how to build the actual API. The Server Side Swift with Vapor video course can get you started.

Did you enjoy this tutorial? I hope it’s useful to manage the states of all the apps you’ll build! If you have any questions or insights to share, I’d love to hear from you in the comments forum below.