Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Reviews SwiftUI code for deprecated APIs, data flow, navigation, accessibility, and performance issues.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/performance.md
1# Performance23- When toggling modifier values, prefer ternary expressions over if/else view branching to avoid `_ConditionalContent`, preserve structural identity, and avoid repeatedly recreating underlying platform views.4- Avoid `AnyView` unless absolutely required. Use `@ViewBuilder`, `Group`, or generics instead.5- If a `ScrollView` has an opaque, static, and solid background, prefer to use `scrollContentBackground(.visible)` to improve scroll-edge rendering efficiency.6- It is more efficient to break views up by making dedicated SwiftUI views rather than place them into computed properties or methods. Using `@ViewBuilder` on a property or method does not solve this; breaking views up is strongly preferred.7- Always ensure view initializers are kept as small and simple as possible, avoiding any non-trivial work. Flag any work that can be moved into a `task()` modifier to be run when the view is shown.8- Similarly, assume each view’s `body` property is called frequently – if logic such as sorting or filtering can be moved out of there easily, it should be.9- Avoid creating properties to store formatters such as `DateFormatter` unless they are required. A more natural approach is to use `Text` with a format, like this: `Text(Date.now, format: .dateTime.day().month().year())` or `Text(100, format: .currency(code: "USD"))`.10- Avoid expensive inline transforms in `List`/`ForEach` initializers (e.g. `items.filter { ... }`) when they are repeated often.11- Prefer deriving transformed data from the source-of-truth using `let`, or caching in `@State`. However, do not cache derived collections in `@State` unless you also own explicit invalidation logic to avoid stale UI.12- For large data sets in `ScrollView`, use `LazyVStack`/`LazyHStack`; flag eager stacks with many children.13- Prefer using `task()` over `onAppear()` when doing async work, because it will be cancelled automatically when the view disappears.14- Avoid storing escaping `@ViewBuilder` closures on views when possible; store built view results instead.1516Example:1718```swift19// Anti-pattern: stores an escaping closure on the view.20struct CardView<Content: View>: View {21let content: () -> Content2223var body: some View {24VStack(alignment: .leading) {25content()26}27.padding()28.background(.ultraThinMaterial)29.clipShape(.rect(cornerRadius: 8))30}31}3233// Preferred: store the built view value; the synthesized init handles calling the builder.34struct CardView<Content: View>: View {35@ViewBuilder let content: Content3637var body: some View {38VStack(alignment: .leading) {39content40}41.padding()42.background(.ultraThinMaterial)43.clipShape(.rect(cornerRadius: 8))44}45}46```47