← Back to list

Mastering Elegant Pagination in SwiftUI Using Modern Swift Concurrency

Infinite scrolling is a staple of modern mobile applications, but implementing it correctly has historically been a headache. With the…

Константин Клинов · 2026-06-08 08:53 · 5 claps · 1.7 min read
#swiftui #iosdev #swiftlang #mobileappdevelopmentindia #software-engineering
Open on Medium ↗
Wiki topics: HIS · History 📱 · Mobile Development

Mastering Elegant Pagination in SwiftUI Using Modern Swift Concurrency

Infinite scrolling is a staple of modern mobile applications, but implementing it correctly has historically been a headache. With the enforcement of Swift 6 Strict Concurrency Checking, the old workarounds utilizing @Published wrappers and loosely managed onAppear closures are no longer acceptable.

Today, we will walk through a robust, thread-safe, and elegant pagination implementation utilizing @Observable, @MainActor, and structured tasks.

The Modern Concurrency Paradigm

In the current ecosystem, avoiding data races is a compiler requirement, not just a suggestion. To achieve smooth pagination, we must ensure two things:

  1. Background Execution: The actual data fetching must not block the UI.
  2. Main Thread Mutations: Updating the list array must happen strictly on the main thread.

Step 1: The @Observable View Model

By marking our class with @Observable and @MainActor, we ensure our UI reacts instantly to changes and all properties are isolated safely.

import SwiftUI

@MainActor
@Observable
final class PaginationViewModel {
    private(set) var items: [String] = []
    private(set) var isLoading = false
    private var currentPage = 1
    private(set) var canLoadMore = true

    func loadNextPage() async {
        // Prevent duplicate concurrent requests
        guard !isLoading && canLoadMore else { return }

        isLoading = true
        // Ensure isLoading is reset regardless of success or failure
        defer { isLoading = false } 

        do {
            let newItems = try await fetchItems(page: currentPage)
            if newItems.isEmpty {
                canLoadMore = false
            } else {
                items.append(contentsOf: newItems)
                currentPage += 1
            }
        } catch {
            print("Pagination error: \(error)")
        }
    }

    // Mock network call
    private func fetchItems(page: Int) async throws -> [String] {
        try await Task.sleep(for: .seconds(1)) 
        return (1...20).map { "Item \($0 + (page - 1) * 20)" }
    }
}

Step 2: The View Implementation

SwiftUI’s .task modifier is the hero here. By attaching it to a ProgressView at the bottom of our list, it triggers the fetch operation only when the user scrolls near the end. Furthermore, .task is bound to the view's lifecycle—if the user navigates away, the network request is automatically cancelled.

struct PaginatedListView: View {
    @State private var viewModel = PaginationViewModel()

    var body: some View {
        NavigationStack {
            List {
                ForEach(viewModel.items, id: \.self) { item in
                    Text(item)
                        .padding(.vertical, 8)
                }

                // Pagination Trigger
                if viewModel.canLoadMore {
                    ProgressView()
                        .frame(maxWidth: .infinity)
                        .padding()
                        .task {
                            await viewModel.loadNextPage()
                        }
                }
            }
            .navigationTitle("Modern Pagination")
            // Initial Data Load
            .task {
                if viewModel.items.isEmpty {
                    await viewModel.loadNextPage()
                }
            }
        }
    }
}

Open to New Opportunities

I am an experienced Senior iOS Developer actively looking for a new role in a product team. I specialize in building highly scalable, beautifully animated applications utilizing modern Swift architectures.


메타데이터
post_id
68ebbca7e853
slug
mastering-elegant-pagination-in-swiftui-using-modern-swift-concurrency-68ebbca7e853
url
https://medium.com/@kost9klinov/mastering-elegant-pagination-in-swiftui-using-modern-swift-concurrency-68ebbca7e853
canonical_url
https://medium.com/@kost9klinov/mastering-elegant-pagination-in-swiftui-using-modern-swift-concurrency-68ebbca7e853
author_url
https://medium.com/@kost9klinov
status
ok
fetched_at
2026-07-10 08:54:07