Slash Command
/data
It is important that SwiftUI body code and logic code be kept separate in order to make code easier to read, write, and maintain. That usually means placing code into methods rather than inline in the `body` property, but often also means carving functionality out into separate `@Observable` classes.
From swiftuiInstall
1
Run in your terminal$
npx claudepluginhub fradser/dotclaude --plugin swiftuiDetails
Namespace
swiftui-review/references/Command Content
Data flow, shared state, and property wrappers
It is important that SwiftUI body code and logic code be kept separate in order to make code easier to read, write, and maintain. That usually means placing code into methods rather than inline in the body property, but often also means carving functionality out into separate @Observable classes.
These rules help ensure code is efficient and works well in the long term.
Shared state
@Observableclasses must be marked@MainActorunless the project has Main Actor default actor isolation. Flag any@Observableclass missing this annotation.- All shared data should use
@Observableclasses with@State(for ownership) and@Bindable/@Environment(for passing). - Strongly prefer not to use
ObservableObject,@Published,@StateObject,@ObservedObject, or@EnvironmentObjectunless they are unavoidable, or if they exist in legacy/integration contexts when changing architecture would be complicated.
Local state
@Stateshould be markedprivateand only owned by the view that created it.- If a view stores a class instance that contains expensive-to-recompute data, e.g.
CIContext, it can be stored using@Stateeven though it is not an observable object. This effectively uses@Stateas a cache – storing something persistently, but not doing any change tracking on it since it's not an observable object.
Bindings
- Strongly prefer to avoid creating bindings using
Binding(get:set:)in view body code. It is much cleaner and simpler to use a binding provided by@State,@Bindingor similar, then useonChange()to trigger any effects. - If the user needs to enter a number into a
TextField, bind theTextFieldto a numeric value such asIntorDouble, then use itsformatinitializer like this:TextField("Enter your score", value: $score, format: .number). Apply either.keyboardType(.numberPad)(for integers) or.keyboardType(.decimalPad)(for floating-point numbers) as appropriate. Using the modifier alone is not sufficient.
Working with data
- Prefer to make structs conform to
Identifiablerather than usingid: \.somePropertyin SwiftUI code. - Never attempt to use
@AppStorageinside an@Observableclass, even if marked@ObservationIgnored– it will not trigger view updates when a change happens.
If the project uses SwiftData with CloudKit
- Never use
@Attribute(.unique). - Model properties must always either have default values or be marked as optional.
- All relationships must be marked optional.
Other plugins with /data
Stats
Parent Repo Stars474
Parent Repo Forks37
Last CommitMar 9, 2026