Xcode 26 turned the coding assistant into a pluggable instrument: ChatGPT by default, Claude with an API key, or a fully local model through LM Studio — all with project context, in-editor edits and fix-error loops. The craft is picking the right model per job and keeping SwiftUI iteration anchored to previews and playgrounds.
Tier: Core · Workflow area: Mobile engineering & release
This playbook sets up the multi-model rotation and the three loops that pay daily: SwiftUI generation against your components, #Playground iteration for logic, and the fix-error cycle for build failures.
@Observable, @State, @Binding), layout debugging.Skip it for storyboard archaeology and complex Interface Builder work; assistants are weakest where the source of truth is a visual editor file.
localhost, added as a local provider.Assign models to jobs, explicitly. Write the rotation down for the team:
@Observable, tricky generics or concurrency errors.Generate SwiftUI against your system, not against Apple defaults. Anchor every generation prompt with references the assistant can open:
Create a PaywallView.
Use our components: PrimaryButton, Card, and the Typography and
ColorTokens definitions in DesignSystem/. Match the state pattern in
SettingsView (an @Observable ViewModel with a UiState enum).
Include states: loading, loaded(products), error(retryable), and a
redeem-code empty branch. Add a #Preview for each state.
Because Xcode's assistant has project context, naming real files beats describing conventions. Review the edit diff before accepting — accept-per-file, not accept-all.
Iterate logic in #Playground before it touches the app. For parsing, pricing math, date logic — anything with edge cases — have the assistant write a #Playground block next to the code and show inline results:
Write a #Playground exercising ReceiptParser.parse with: a valid
receipt, an expired one, a malformed JSON payload, and an empty
string. Show the parsed result or error for each.
This is the Swift equivalent of a REPL loop: you see real outputs inline, and the playground becomes the seed of the unit test the assistant writes afterwards.
Run the fix-error loop with suspicion. On a build failure, the inline "fix" affordance feeds the error plus context to the model. Accept its mechanical fixes (missing await, wrong argument label, Sendable conformance) freely; for anything that changes logic — force-unwraps added, @MainActor sprinkled to silence warnings, try? swallowing errors — reject and ask instead:
Explain why this error occurs and give two alternative fixes with
trade-offs. Do not apply anything yet.
Close every session with preview-verified states. Before committing, render each #Preview variant in the canvas, toggle dark mode and at least one large Dynamic Type size, and run the app once on a simulator for the flow you touched. The preview canvas is your visual harness; generated SwiftUI that was never rendered is unreviewed code.
Multi-model is a routing decision you make once per task — frontier cloud for judgment, local for privacy and volume — while the verification loop never changes: previews for every state, playgrounds for every edge case, and no accepted fix you cannot explain.
#Playground (or the unit test grown from it) whose outputs you actually read.try?-swallowed errors, or warning-silencing attributes introduced by fix-error loops (git diff audit).@Observable and the newer framework surfaces.For NDA or air-gapped codebases, run the entire loop on the LM Studio provider: same prompts, same preview-and-playground verification, no code leaving the machine. Keep a written note of which projects are local-only so nobody flips the model picker out of habit. Where even a local general-purpose model is disallowed, fall back to Xcode's on-device predictive completion only.
The model picker is per-session and easy to fat-finger. Before pasting client code, glance at which provider is active — a cloud logo in the corner is the whole compliance story.