1 · Why Grids? – A Quick Primer

Purpose

Grids let you arrange views in rows × columns while preserving SwiftUI’s declarative style. They balance the straightforwardness of VStack/HStack with the performance of collection‑style containers.

When to Use

Lazy grids (LazyVGrid/LazyHGrid) and the new Grid have different performance profiles—pick the right one for your target OS version.

2 · Grid & GridRow Basics

Syntax

Grid(alignment: .leading, horizontalSpacing: 16, verticalSpacing: 12) {
    GridRow {
        Text("CPU").bold()
        Text("A17 Pro")
        Text("6‑core")
    }
    Divider().gridCellColumns(3)   // spans full row
    GridRow {
        Text("RAM")
        Text("8 GB")
        Text("LPDDR5")
    }
}
.padding()
Key API Surface
  • Grid(_:alignment:horizontalSpacing:verticalSpacing:) – container initializer
  • GridRow(_:) – groups values for a single row
  • gridCellColumns(_ count:Int) – column‑spanning modifier
  • gridColumnAlignment(_ alignment:) – per‑column override
Column Alignment

All cells in a column inherit the grid’s alignment unless overridden. Combine with .frame(maxWidth:.infinity,alignment:.trailing) for numeric tables.

3 · LazyVGridLazyHGrid

Why “Lazy”?

Cells are created on‑demand as they scroll into view within a ScrollView, reducing memory usage for long lists.

GridItem
  • .fixed(CGFloat) – fixed width / height
  • .flexible(min:CGFloat?, max:CGFloat?)
  • .adaptive(min:CGFloat, max:CGFloat? = nil)

let columns = [
    GridItem(.adaptive(min: 80), spacing: 12)
]

ScrollView {
    LazyVGrid(columns: columns, spacing: 16) {
        ForEach(0..<100) { index in
            RoundedRectangle(cornerRadius: 12)
                .fill(.blue.opacity(0.7))
                .aspectRatio(1, contentMode: .fit)
                .overlay(Text("\(index)").foregroundColor(.white))
        }
    }
    .padding()
}

Use pinnedViews to pin headers/footers when mixing Section in Lazy*Grid.

4 · Common Patterns & Recipes

Adaptive Photo Grid

struct PhotoGrid: View {
    let photos:[UIImage]

    private var columns:[GridItem] {
        [GridItem(.adaptive(min: 100), spacing: 8)]
    }

    var body: some View {
        ScrollView {
            LazyVGrid(columns: columns, spacing: 8) {
                ForEach(photos, id:\.self) { img in
                    Image(uiImage: img)
                        .resizable()
                        .aspectRatio(1, contentMode: .fill)
                        .clipped()
                        .cornerRadius(10)
                }
            }
            .padding()
        }
    }
}
Calendar‑Style Grid

struct MonthView: View {
    let days = Calendar.current.shortWeekdaySymbols
    let dates:[Date]   // computed for the month

    var body: some View {
        Grid(horizontalSpacing: 4, verticalSpacing: 4) {
            // weekday headers
            GridRow {
                ForEach(days, id:\.self){ Text($0).font(.caption2).bold() }
            }
            // dates
            ForEach(dates, id:\.self) { date in
                GridRow {
                    Text(Calendar.current.component(.day, from: date).description)
                        .frame(maxWidth:.infinity)
                        .padding(6)
                        .background(.thinMaterial)
                        .cornerRadius(4)
                }
            }
        }
    }
}

5 · Advanced Topics

Animation & Transitions
  • Use .transaction or withAnimation to animate insertions/removals.
  • Combine with .matchedGeometryEffect for smooth cell re‑orderings.
Reading Layout Info

Measure a cell with GeometryReader to size content proportionally (e.g., square thumbnails).

Performance Guidelines
  1. Prefer Lazy*Grid for large, scrollable content.
  2. For small static tables (≤ ~50 views), Grid is often simpler & faster.
  3. Avoid heavy view hierarchies inside each cell—factor out into lightweight sub‑views.

6 · macOS – NSGridView

Swift (UIKit‑style) Example

let grid = NSGridView(views: [
    [NSTextField(labelWithString:"CPU"), NSTextField(labelWithString:"M3 Max")],
    [NSTextField(labelWithString:"Cores"), NSTextField(labelWithString:"40‑core GPU")]
])
grid.rowSpacing    = 8
grid.columnSpacing = 12
grid.yPlacement    = .center

Unlike SwiftUI grids, NSGridView relies on Auto Layout constraints and is not lazy‑loaded. Wrap it in NSViewRepresentable for use inside SwiftUI.

7 · Best Practices Checklist

  • Choose the grid style aligned with OS minimum: Grid (iOS 16+), Lazy*Grid (iOS 14+).
  • Adopt .adaptive columns for responsive widths.
  • Wrap the grid in ScrollView for vertical/horizontal paging when content might overflow.
  • Profile with Instruments › SwiftUI track—watch for off‑screen view creation.
  • Accessibility: add .accessibilityLabel to cells and use .accessibilitySortPriority for reading order.