Slash Command
/performance
- 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.
From swiftuiInstall
1
Run in your terminal$
npx claudepluginhub fradser/dotclaude --plugin swiftuiDetails
Namespace
swiftui-review/references/Command Content
Performance
- 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. - Avoid
AnyViewunless absolutely required. Use@ViewBuilder,Group, or generics instead. - If a
ScrollViewhas an opaque, static, and solid background, prefer to usescrollContentBackground(.visible)to improve scroll-edge rendering efficiency. - It is more efficient to break views up by making dedicated SwiftUI views rather than place them into computed properties or methods. Using
@ViewBuilderon a property or method does not solve this; breaking views up is strongly preferred. - 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. - Similarly, assume each view’s
bodyproperty is called frequently – if logic such as sorting or filtering can be moved out of there easily, it should be. - Avoid creating properties to store formatters such as
DateFormatterunless they are required. A more natural approach is to useTextwith a format, like this:Text(Date.now, format: .dateTime.day().month().year())orText(100, format: .currency(code: "USD")). - Avoid expensive inline transforms in
List/ForEachinitializers (e.g.items.filter { ... }) when they are repeated often. - Prefer deriving transformed data from the source-of-truth using
let, or caching in@State. However, do not cache derived collections in@Stateunless you also own explicit invalidation logic to avoid stale UI. - For large data sets in
ScrollView, useLazyVStack/LazyHStack; flag eager stacks with many children. - Prefer using
task()overonAppear()when doing async work, because it will be cancelled automatically when the view disappears. - Avoid storing escaping
@ViewBuilderclosures on views when possible; store built view results instead.
Example:
// Anti-pattern: stores an escaping closure on the view.
struct CardView<Content: View>: View {
let content: () -> Content
var body: some View {
VStack(alignment: .leading) {
content()
}
.padding()
.background(.ultraThinMaterial)
.clipShape(.rect(cornerRadius: 8))
}
}
// Preferred: store the built view value; the synthesized init handles calling the builder.
struct CardView<Content: View>: View {
@ViewBuilder let content: Content
var body: some View {
VStack(alignment: .leading) {
content
}
.padding()
.background(.ultraThinMaterial)
.clipShape(.rect(cornerRadius: 8))
}
}
Other plugins with /performance
Stats
Parent Repo Stars474
Parent Repo Forks37
Last CommitMar 9, 2026