NEW Tool! SwiftFairy: Local Swift and SwiftUI code reviews for your coding agent. Learn more ...NEW Tool! SwiftFairy:Local code reviews for your agents. Learn more...
← All SwiftFairy Scrolls

SwiftFairy Scroll

Proper SwiftUI

Correct subtle bugs and performance issues in data flow, state ownership, and view updates by using SwiftUI as it was designed to be used.

What your agent can improve

Data flow

Help your agent trace how data moves between views and resolve issues in how it is shared, so each view receives the data it needs.

State ownership

Give your agent guidance on where state belongs and which view owns it, helping it manage that state throughout the view's lifecycle.

View identity

Identify changes in view identity that can unexpectedly discard state, with guidance and code examples to help your agent preserve it.

View updates and performance

Find dependencies that trigger unnecessary view updates and repeated work, helping your agent improve performance by using SwiftUI as it was designed to be used.

Example findings

These examples show the patterns SwiftFairy flags and the guidance your agent can use to address them. Highlighted lines mark the code to review; each finding indicates whether the guidance is a requirement, recommendation, or consideration.

Must not

Extract computed view builders into views

When we use a helper function or a computed property to return some View, we are simply moving a piece of the parent's body logic to a different location in the same component. This does not give the extracted code independent dependency tracking. When the parent reevaluates its body, the helper's logic runs again, even if the data it uses hasn't changed.

Pattern flagged for review

struct AnimalDetailView: View {
     let animal: Animal

     var body: some View {
         habitatSection
     }

     @ViewBuilder
     private var habitatSection: some View {
         AnimalInfoSection(
             header: "Habitat",
             info: animal.habitatName
         )
     }
}

A possible improvement

// In AnimalDetailView.body:
AnimalHabitatSection(
     habitatName: animal.habitatName
)

struct AnimalHabitatSection: View {
     let habitatName: String

     var body: some View {
         AnimalInfoSection(
             header: "Habitat",
             info: habitatName
         )
     }
}

Extract the section into a separate view struct, passing it only the information it needs to display its contents. When the parent updates, a new instance of AnimalHabitatSection is created. If its habitat name hasn't changed, SwiftUI can skip the execution of its body.

Should not

Avoid a variable number of views in ForEach blocks

When a ForEach inside a list produces a variable number of rows per element, SwiftUI must evaluate its content for each item in the list to determine which rows exist. Filtering the collection beforehand allows rows to be created lazily.

Pattern flagged for review

ForEach(walks) { walk in
     if walk.isShort {
         Text(walk.name)
     }
}

A possible improvement

ForEach(shortWalks) { walk in
     Text(walk.name)
}

Prepare shortWalks when the source data or filter changes. ForEach then receives a collection with known membership and produces exactly one row per element.

Put the findings to work

Ask your agent to review a code change or a complete codebase with SwiftFairy. Your agent uses the findings and their accompanying code examples to resolve issues in your code.

How to use SwiftFairy

Try Proper SwiftUI free for one day

Activate your trial in the SwiftFairy app. No card or payment information is required.

Choose lifetime access, a fixed term, or a subscription for this Scroll, or get all three together in a bundle.

Explore the other Scrolls