Chapters

Hide chapters

SwiftUI Cookbook

Live Edition · iOS 16.4 · Swift 5.8.1 · Xcode 14.3.1

Create an Infinitely Scrolling List in SwiftUI
Written by Team Kodeco

Creating an infinitely scrolling list in SwiftUI can help provide a seamless and fluid user experience, especially when dealing with large sets of data. It’s often used in applications that load content dynamically from a server as the user scrolls.

Here’s how you might set up a simple infinitely scrolling list in SwiftUI:

struct ContentView: View {
  @State private var numbers: [Int] = Array(1...20)
  @State private var isLoading = false
  @State private var isFinished = false

  var body: some View {
    NavigationStack {
      List {
        ForEach(numbers, id: \.self) { number in
          Text("Row \(number)")
        }

        if !isFinished {
          ProgressView()
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .foregroundColor(.black)
            .foregroundColor(.red)
            .onAppear {
              loadMoreContent()
            }
        }
      }
      .navigationTitle("Infinite List")
    }
  }

  func loadMoreContent() {
    if !isLoading {
      isLoading = true
      // This simulates an asynchronus call
      DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
        let moreNumbers = numbers.count + 1...numbers.count + 20
        numbers.append(contentsOf: moreNumbers)
        isLoading = false
        if numbers.count > 250 {
          isFinished = true
        }
      }
    }
  }
}

Here’s what your preview should look like:

An infinitely scrolling list in SwiftUI.
An infinitely scrolling list in SwiftUI.

Try scrolling to the bottom, how many numbers does your list show?

In this example, you first create an array of numbers that you use to populate your list. You also include a Boolean isLoading state variable that you’ll use to control when you’re currently loading more content.

Inside your List view, you use the ForEach loop to generate the list items. You also include a conditional view that will display a ProgressView (a spinning indicator) when the isFinished state variable is false. Imagine we had a server responding with data. isFinished would become true when the server has no more data to send us.

The onAppear modifier on the ProgressView view triggers the loadMoreContent() function when the view first appears on the screen. onAppear is on the ProgressView because we only want to load more data when the user is scrolling down and expects to see more. Imagine trying to load all the data at once!

Inside loadMoreContent, we simulate an asynchronous loading operation. If we’re not currently loading more content (indicated by isLoading being false), we set isLoading to true and then dispatch a delayed task. After the delay, we append more numbers to our array and set isLoading back to false. This simulates fetching more data from a server. We then check to see if numbers has more than 100 entries. If so, we set isFinished to true. This simulates the end of the list and signals there is no more data to fetch.

With this implementation, you can create a simple yet infinitely scrolling list in SwiftUI. This can greatly enhance the user experience, especially when dealing with large data sets. Try it out in your app today!

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.