Skip to content

Previewing Loading States in SwiftUI Without Changing Production Code

A preview-only helper that simulates network delays so you can see loading states in SwiftUI previews.

The Challenge

When building views that depend on asynchronous data, you typically have a loading state that shows a spinner or placeholder. In production, this state appears briefly while data loads from the network or database. But in SwiftUI previews, your mock data is available instantly, so the loading state flashes by too fast to inspect – or never appears at all.

A Preview-Only Delay Helper

The solution is a small helper that introduces an artificial delay, but only in preview or debug contexts. Here is the pattern:

struct DelayedStatePreview<Content: View>: View {
   @State private var isLoaded = false
   let delay: Duration
   let content: (Bool) -> Content

   init(
      delay: Duration = .seconds(2),
      @ViewBuilder content: @escaping (Bool) -> Content
   ) {
      self.delay = delay
      self.content = content
   }

   var body: some View {
      content(isLoaded)
         .task {
            try? await Task.sleep(for: delay)
            isLoaded = true
         }
   }
}

You use it in a preview like this:

#Preview {
   DelayedStatePreview { isLoaded in
      if isLoaded {
         ArticleListView(articles: mockArticles)
      } else {
         LoadingView()
      }
   }
}

Code example showing the preview helper in context

Why This Matters

The key benefit is that your production code stays clean. You are not adding artificial delays or debug flags to your actual views. The helper exists purely at the preview layer, giving you a way to visually verify that your loading states look correct, that transitions animate smoothly, and that layout does not jump when data arrives.

This is especially useful for views with skeleton loaders or shimmer effects where the visual quality of the loading state is part of the user experience.

Found this helpful? Follow me on Bluesky and Mastodon for more Swift tips and indie dev updates.