Agent skills for iOS, iPadOS, Swift, SwiftUI, and modern Apple framework development.
71
89%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Advisory
Suggest reviewing before use
Use grids for dense visual collections where row-based layouts waste space or make scanning harder.
Good fits:
Default to LazyVGrid for vertically scrolling collections on iOS. Reach for
Grid when content is small and non-scrollable, or when you need explicit row
composition rather than a large lazy container.
LazyVGridUse for the common iPhone/iPad case: many items, vertical scrolling, and a column definition that should adapt to width.
LazyHGridUse when horizontal scrolling is the dominant interaction and rows are easier to define than columns.
GridUse when:
GridRow composition instead of a repeated collection layoutFor large scrolling datasets, LazyVGrid is usually the safer default.
Use .adaptive when you want the number of columns to respond to available
width.
let columns = [GridItem(.adaptive(minimum: 120, maximum: 240))]This is the best default for icon pickers, template choosers, and photo grids that should scale naturally across iPhone and iPad sizes.
Use multiple .flexible columns when you want a predictable column count.
let columns = [
GridItem(.flexible(minimum: 100)),
GridItem(.flexible(minimum: 100)),
GridItem(.flexible(minimum: 100)),
]This works well when design requires a fixed 2-column or 3-column rhythm.
Use .fixed only when the design truly requires exact widths. Fixed columns are
less resilient across device sizes and dynamic type changes.
Grid cells should usually define their own shape without reading parent geometry.
Preferred sizing tools:
.aspectRatio(1, contentMode: .fit) for square thumbnails.frame(maxWidth: .infinity) when content should fill the available columnAvoid GeometryReader inside lazy containers. It defeats lazy layout and adds
extra measurement work.
let columns = [GridItem(.adaptive(minimum: 120, maximum: 240))]
LazyVGrid(columns: columns) {
ForEach(icons) { icon in
Button {
select(icon)
} label: {
ZStack(alignment: .bottomTrailing) {
Image(icon.previewName)
.resizable()
.aspectRatio(contentMode: .fit)
.clipShape(.rect(cornerRadius: 6))
if icon.isSelected {
Image(systemName: "checkmark.seal.fill")
.padding(4)
.tint(.green)
}
}
}
.buttonStyle(.plain)
.contentShape(Rectangle())
}
}Why this works:
LazyVGrid(
columns: [
.init(.flexible(minimum: 100), spacing: 4),
.init(.flexible(minimum: 100), spacing: 4),
.init(.flexible(minimum: 100), spacing: 4),
],
spacing: 4
) {
ForEach(items) { item in
ThumbnailView(item: item)
.aspectRatio(1, contentMode: .fit)
.clipShape(.rect(cornerRadius: 8))
}
}Use this when the design language wants a consistent three-up gallery instead of an adaptive count.
Sectioned grids work well for grouped content like categories or recents.
LazyVGrid(columns: [GridItem(.adaptive(minimum: 140))]) {
ForEach(sections) { section in
Section {
ForEach(section.items) { item in
Tile(item: item)
}
} header: {
Text(section.title)
.font(.headline)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.top)
}
}
}Keep headers visually lightweight. Dense grids lose scan efficiency when every section header is oversized or heavily decorated.
Grid interactions should stay obvious and forgiving.
Useful defaults:
.contentShape(Rectangle())For multi-select grids, prefer clear selection affordances instead of hidden state changes triggered only by long press.
LazyVGrid for large collections.ForEach.If scrolling stutters, profile image decoding, per-cell overlays, and repeated state invalidation before changing the grid structure itself.
A dense grid should still feel calm and legible, not like a wall of competing badges and borders.
ForEach.GeometryReader inside lazy containers (LazyVGrid,
LazyHGrid, LazyVStack, LazyHStack). It forces eager measurement and
defeats lazy loading. Use .aspectRatio for sizing, or .onGeometryChange
(iOS 18+) if you need to read dimensions.skills
accessorysetupkit
references
activitykit
references
adattributionkit
references
alarmkit
references
app-clips
app-intents
references
app-store-optimization
app-store-review
apple-on-device-ai
appmigrationkit
references
audioaccessorykit
references
authentication
references
avkit
references
background-processing
references
browserenginekit
references
callkit
references
carplay
references
cloudkit
references
contacts-framework
references
core-bluetooth
references
core-data
core-motion
references
core-nfc
references
coreml
references
cryptokit
references
cryptotokenkit
references
debugging-instruments
device-integrity
references
dockkit
references
energykit
references
eventkit
references
financekit
references
focus-engine
gamekit
references
healthkit
references
homekit
references
ios-accessibility
ios-localization
ios-networking
ios-simulator
references
mapkit
metrickit
references
musickit
references
natural-language
references
paperkit
references
passkit
references
pdfkit
references
pencilkit
references
permissionkit
references
photokit
push-notifications
realitykit
references
relevancekit
references
scenekit
references
sensorkit
references
speech-recognition
spritekit
references
storekit
swift-api-design-guidelines
swift-architecture
swift-charts
references
swift-codable
swift-concurrency
swift-formatstyle
swift-language
swift-security
references
swift-testing
swiftdata
swiftlint
swiftui-animation
swiftui-gestures
references
swiftui-layout-components
swiftui-liquid-glass
references
swiftui-patterns
swiftui-performance
swiftui-uikit-interop
swiftui-webkit
tabletopkit
references
tipkit
references
vision-framework
weatherkit
references
widgetkit
references