Guide

Why Does My SwiftUI Layout Break When Data Gets Large?

AI

AI Agent Skills

8 min

The Problem: Your SwiftUI App Stutters or Freezes with Real Data

You built a SwiftUI app that looks great in previews. The settings screen is smooth. The small test list scrolls perfectly. Then you connect it to a real data source—hundreds of items, a live feed, or a media gallery—and everything falls apart.

The list stutters when scrolling. The grid takes seconds to appear. The scroll view jumps unpredictably. You add more data and the app becomes unresponsive. You try wrapping things in ScrollView and adding ForEach, but the performance problems persist.

This is a common experience for developers moving from prototype to production in SwiftUI. The framework is powerful, but its layout system has specific performance characteristics that are not obvious until you hit scale.

Why This Happens

SwiftUI's default stacks (VStack, HStack, ZStack) are eager—they render every child view immediately, regardless of whether it is on screen. For a settings screen with 10 rows, this is fine. For a feed with 1,000 items, it means creating and laying out all 1,000 views before the user sees anything.

Grids have similar issues. Using Grid with many cells forces SwiftUI to calculate positions for every cell upfront. Lists are better because they reuse rows, but incorrect configuration—like placing a GeometryReader inside a lazy container—can defeat the reuse mechanism and cause eager measurement of every row.

Scroll views add another layer of complexity. Without proper scroll position tracking, you cannot implement features like "scroll to bottom" for a chat app or "jump to section" for a long document. The default ScrollView also does not handle mixed content layouts well—combining a horizontal chip selector with a vertical feed, for example.

What a Good Solution Should Change

A practical fix should do three things:

  1. Use lazy loading by default for any collection that could grow. This means LazyVStack instead of VStack inside scroll views, and LazyVGrid instead of Grid for galleries.
  2. Provide clear patterns for common layout scenarios. You should not have to guess whether to use List or ScrollView with lazy stacks. You should know that List is for settings and feeds where row reuse and accessibility matter, while ScrollView with lazy stacks is for custom layouts, horizontal scrolling, or mixed content.
  3. Handle scroll position declaratively. You should be able to track scroll position, scroll programmatically, and respond to scroll events without writing imperative UIScrollView bridging code.

The goal is not to learn every SwiftUI layout modifier. It is to have a small set of reliable patterns that you can apply to specific problems: data-driven grids, feed lists, settings screens, search interfaces, and scroll-driven reveals.

Introducing the SwiftUI Layout Components Skill

The SwiftUI Layout Components skill is a curated set of layout and component patterns for SwiftUI apps targeting iOS 17 and later. It is not a library you install. It is a reference document that your AI coding agent can use to generate correct, performant SwiftUI code for specific layout problems.

The skill covers stacks, grids, lists, scroll views, forms, controls, search interfaces, and overlay patterns. Each pattern includes code examples, guidance on when to use it, and common mistakes to avoid.

How It Works in Practice

When you ask your AI agent to build a screen, the skill provides the agent with the right pattern for the job. For example:

  • "Build a photo gallery that works on iPhone and iPad" → The agent uses LazyVGrid with .adaptive columns and .aspectRatio for cells.
  • "Create a settings screen with grouped options" → The agent uses List with .listStyle(.insetGrouped) and Section blocks.
  • "Build a chat view that scrolls to the latest message" → The agent uses ScrollView with LazyVStack, .scrollTargetLayout(), and ScrollPosition tracking.
  • "Add a search bar to the explore screen" → The agent uses .searchable with .searchScopes and debounced async results.

The skill does not try to cover animations, transitions, or timing. Those are separate concerns. It focuses on layout structure and component configuration.

When This Skill Applies

This skill is useful when you are building:

  • Data-driven layouts that need to handle hundreds or thousands of items without performance degradation.
  • Collection views like photo galleries, icon pickers, or media browsers that need adaptive grid layouts.
  • Feed-style lists with pull-to-refresh, swipe actions, or section headers.
  • Settings screens with grouped controls, toggles, pickers, and sliders.
  • Search interfaces with scoped search, debounced results, and loading states.
  • Scroll-driven UI like chat views, paged detail reveals, or scroll-to-top functionality.
  • Overlay and presentation patterns for sheets, popovers, and transient UI.

If you are building a simple two-screen app with static content, you probably do not need this skill. The default SwiftUI patterns will work fine.

What the Skill Covers

Stack Layouts

The skill distinguishes between eager stacks (VStack, HStack, ZStack) for small, fixed content and lazy stacks (LazyVStack, LazyHStack) for large or dynamic collections inside scroll views. It explains when to use each and provides code examples for both.

Grid Layouts

It covers LazyVGrid with both .adaptive columns (for layouts that scale across device sizes) and .flexible columns (for fixed column counts). It explains how to use .aspectRatio for cell sizing and warns against placing GeometryReader inside lazy containers, which forces eager measurement and defeats lazy loading.

List Patterns

The skill provides patterns for feed-style lists with .listStyle(.plain) and settings lists with .listStyle(.insetGrouped). It covers row customization with .listRowInsets and .listRowSeparator, pull-to-refresh with .refreshable, and swipe actions. It also explains when to use List versus ScrollView with lazy stacks—List for built-in row reuse and accessibility, ScrollView for custom layouts and horizontal scrolling.

ScrollView and ScrollPosition

It covers ScrollView with lazy stacks for custom layouts and horizontal scrolling. It explains ScrollPosition for declarative, bidirectional scroll position tracking and programmatic scrolling. It shows how to use .scrollTargetLayout() and stable targets for reliable jump-to-id behavior. It also covers safeAreaInset(edge:) for pinning content above the keyboard.

Form and Controls

The skill provides patterns for Form with Section blocks, grouped controls, and .formStyle(.grouped). It covers Toggle, Picker, Slider, DatePicker, and TextField with proper binding to @State, @Binding, or @AppStorage. It explains how to use @FocusState for keyboard focus management in input-heavy forms.

Searchable

It covers .searchable for adding native search UI, .searchScopes for multiple search modes, and .task(id:) for debounced async results. It shows how to handle loading states and empty results.

Overlay and Presentation

The skill covers overlay patterns for sheets, popovers, and transient UI. It explains how to use .sheet, .popover, and .confirmationDialog with proper state management.

Capability Boundaries

This skill has clear boundaries:

  • It covers layout and component patterns only. It does not cover animations, transitions, or timing. Those are handled by separate skills.
  • It targets iOS 17 and later. Some patterns (like .scrollEdgeEffectStyle) require iOS 26, but most are backward-compatible to iOS 17.
  • It does not cover custom drawing or graphics. For that, you would need a different skill.
  • It does not cover data layer integration. It assumes you have your data source figured out and focuses on how to display it.

When Not to Use This Skill

Do not use this skill if:

  • You are building a simple app with static content and fewer than 20 items per screen.
  • You need heavy custom animations or complex transition logic.
  • You are targeting iOS 16 or earlier.
  • You need to draw custom shapes or use Metal for graphics.

Setup and Safety

This skill is a reference document, not a library. There is nothing to install. Your AI agent reads the skill file and applies the patterns when generating code.

The skill is part of the swift-ios-skills repository by dpearson2699. The repository has 931 stars and covers multiple iOS development topics including SwiftUI, SwiftData, MapKit, and StoreKit. The license is permissive.

The skill does not execute code or access external services. It is a static reference document. There are no security concerns beyond those inherent in the code patterns it describes.

Repository Signals

The repository is actively maintained and covers a broad range of iOS development topics. The 931 stars indicate community interest and validation. The skill is part of a larger collection, so you can combine it with other skills for networking, data persistence, or map integration.

Before You Use It

Before relying on this skill, check:

  1. Does your AI agent support skill files? The skill is designed for agents like Claude Code, Cursor, and Codex that can read reference documents.
  2. Is your target iOS version compatible? Most patterns work on iOS 17+, but some require iOS 26.
  3. Do you need layout patterns specifically? If your problem is animations, networking, or data persistence, a different skill would be more appropriate.

You can review the full skill documentation and code examples on the SwiftUI Layout Components skill page.

延伸閱讀