From kiln
Transform good SwiftUI code into excellent, HIG-compliant production-ready code
npx claudepluginhub moonlightbyte/kiln# SwiftUI iOS Code Polish Command Elevate your SwiftUI code from good to production-excellent using cutting-edge best practices from iOS 18+ and the latest Apple design patterns. This command applies the 2025 HIG standards, visionOS-inspired design, and performance optimizations from WWDC 2025. ## Instructions Analyze the SwiftUI code and provide a comprehensive polish report that transforms it into excellent production-ready code. Focus on: 1. **Modern State Management** - @Observable macro, @Bindable, Observation framework 2. **Navigation Excellence** - NavigationStack, type-safe rout...
Elevate your SwiftUI code from good to production-excellent using cutting-edge best practices from iOS 18+ and the latest Apple design patterns. This command applies the 2025 HIG standards, visionOS-inspired design, and performance optimizations from WWDC 2025.
Analyze the SwiftUI code and provide a comprehensive polish report that transforms it into excellent production-ready code. Focus on:
Reference the latest WWDC 2025 guidance and Apple Design Resources.
{{#if (or (eq focus "state") (eq focus "all") (not focus))}}
iOS 18+ (@Observable Macro)
@Observable macro instead of ObservableObject protocol@Observable class@Bindable with @State for child view bindings@State only used for local view state (never reference types)@State private var count = 0@StateObject for simple value types@MainActor for UI updates@EnvironmentObject for mutable stateMigration Pattern (iOS 17 -> iOS 18)
// BEFORE (iOS 17 - ObservableObject)
final class EventViewModel: ObservableObject {
@Published var events: [Event] = []
}
// AFTER (iOS 18+ - @Observable)
@Observable
final class EventViewModel {
var events: [Event] = []
}
{{/if}}
{{#if (or (eq focus "performance") (eq focus "all") (not focus))}}
NavigationStack Best Practices
NavigationStack instead of deprecated NavigationView@State private var path = NavigationPath().navigationBackButtonHidden when neededType-Safe Navigation Pattern
// NavigationStack with type-safe routing
NavigationStack(path: $router.path) {
HomeView()
.navigationDestination(for: Route.self) { route in
switch route {
case .eventDetail(let id):
EventDetailView(eventID: id)
case .profile:
ProfileView()
}
}
}
{{/if}}
{{#if (or (eq focus "animations") (eq focus "all") (not focus))}}
Physics-Based Motion
.spring() animations for natural, bouncy motion@Environment(\.accessibilityReduceMotion) in all animations.animation(_:value:) modifier with explicit value bindingsiOS 18 Advanced Animation Features
keyframeAnimator for multi-stage sequential animationsPhaseAnimator for looping animations with phasesmatchedGeometryEffect for shared element transitions.easeInOut, .snappy, .smooth timingReduced Motion Respect Pattern
// GOOD - Respects accessibility preference
@Environment(\.accessibilityReduceMotion) var reduceMotion
var animationDuration: Double {
reduceMotion ? 0 : 0.35
}
.withAnimation(.spring(response: 0.35, dampingFraction: 0.8)) {
isExpanded.toggle()
}
{{/if}}
{{#if (or (eq focus "performance") (eq focus "all") (not focus))}}
View Body Efficiency
@ViewBuilder instead of AnyView for conditional viewsid(_:) provided in all ForEach loopsEquatableView to skip expensive view redrawsList Performance
List instead of ScrollView + VStackLazyVStack, LazyHStack, LazyVGrid for long lists.onAppear avoided; using .task(id:) for async workGPU-Heavy Effects Management
.shadow, .blur, .opacity combined when possible.scaleEffect instead of .frame(width:height:) for minor adjustments.fill() not .background()Environment Performance
@Binding for local mutations, not environmentWWDC 2025 Profiling
{{/if}}
{{#if (or (eq focus "accessibility") (eq focus "all") (not focus))}}
WCAG Compliance (iOS 18+)
.accessibilityLabel (descriptive, not redundant).accessibilityHidden(true).accessibilityElement(children:) when needed.accessibilityEnabled(condition:) for conditional attributes (iOS 18+)VoiceOver Optimization
.accessibilityElement(children: .combine).accessibilityAnnouncement().accessibilityAdjustableAction correctlyDynamic Type Support
.font(.body)) not hardcoded sizesInclusive Color Design
.label, .secondaryLabel) not hardcoded hex.colorSchemeContrast(.increased) for visibility{{/if}}
{{#if (or (eq focus "design") (eq focus "all") (not focus))}}
iOS 26 "Solarium" Design System
.glassEffect() modifier for iOS 26+ design aesthetic.material(.thin), .material(.regular), .material(.thick)Adaptive Lighting (visionOS Inspiration)
@Environment(\.colorScheme)HIG Compliance (2025)
.buttonStyle(.bordered) or .buttonStyle(.plain).ignoresSafeArea() used consciously{{/if}}
{{#if (or (eq focus "concurrency") (eq focus "all") (not focus))}}
@MainActor Isolation
@MainActorDispatchQueue.main needed)@BackgroundActor or explicit Task.detachedTask Management
.task(id:) modifier instead of .onAppear with Task { }Task.isCancelled in long-running operations.task via defer or onDisappearasync let for concurrent operations!) of optionals; using if let or ??Error Handling
Result<Success, Failure> for explicit error handlingNetworkService Pattern (iOS 18+)
@MainActor
final class EventViewModel {
@Observable
final class State {
var events: [Event] = []
var isLoading = false
var error: String?
}
private let networkService: NetworkService
@MainActor var state = State()
func loadEvents() async {
state.isLoading = true
state.error = nil
do {
state.events = try await networkService.fetchEvents()
} catch {
state.error = error.localizedDescription
}
state.isLoading = false
}
}
{{/if}}
{{#if (or (eq focus "all") (not focus))}}
SwiftData Integration (iOS 17+)
@Query macro for data fetching instead of manual observation@Model macro.modelContainer environment modifierCodable Compliance
Codable when neededDecodable implementation for complex JSON structures{{/if}}
{{code}}
Generate a comprehensive polish report following this structure:
## SwiftUI Code Polish Report
### Summary
- **Current State**: [Brief assessment]
- **Target Level**: Production Excellence
- **Polish Opportunities**: [Count] issues found
### Critical Issues (๐ด)
[Issues that block accessibility, crash, or violate HIG]
Each with:
- Line number and description
- Current code snippet
- Polished code snippet
- Explanation of improvement
- Rule: PS-XXX
### Important Issues (๐ )
[Issues that reduce code quality or UX]
### Warnings (๐ก)
[Suboptimal patterns that work but should improve]
### Polish Suggestions (๐)
[Excellence opportunities - cutting-edge patterns]
### Modern Architecture Recommendations
**State Management Pattern**
```swift
[Recommended @Observable pattern]
Navigation Pattern
[Type-safe NavigationStack pattern]
Async/Concurrency Pattern
[@MainActor + .task pattern]
---
## Example Polish Report
### Input Code
```swift
class EventViewModel: ObservableObject {
@Published var events: [Event] = []
@Published var isLoading = false
func loadEvents() {
isLoading = true
DispatchQueue.main.async {
// Network call
self.isLoading = false
}
}
}
struct EventListView: View {
@ObservedObject var viewModel = EventViewModel()
var body: some View {
NavigationView {
ScrollView {
VStack {
ForEach(viewModel.events) { event in
HStack {
VStack(alignment: .leading) {
Text(event.title)
.font(.system(size: 18, weight: .bold))
Text(event.date)
.font(.system(size: 14))
}
Spacer()
}
.padding(12)
.background(Color(red: 0.95, green: 0.95, blue: 0.95))
.cornerRadius(8)
}
}
}
.navigationTitle("Events")
}
}
}
## SwiftUI Code Polish Report: EventListView
### Summary
- **Current State**: Functional iOS 16-era code using deprecated patterns
- **Target Level**: iOS 18+ Production Excellence
- **Polish Opportunities**: 12 modernizations available
### Critical Issues (๐ด)
**Issue 1: Using @ObservedObject for owned instance (Line 29)**
```swift
// CURRENT - Recreates ViewModel on every parent update!
@ObservedObject var viewModel = EventViewModel()
// POLISHED - Use @StateObject for owned instances
@StateObject private var viewModel = EventViewModel()
Severity: ๐ด Critical | Rule: PS-002 The ViewModel is recreated whenever the parent View redraws, losing all state. This is a performance and correctness issue.
Issue 2: Using deprecated @ObservableObject protocol (Line 1)
// CURRENT (iOS 17)
class EventViewModel: ObservableObject {
@Published var events: [Event] = []
}
// POLISHED (iOS 18+)
@Observable
final class EventViewModel {
var events: [Event] = []
}
Severity: ๐ด Critical | Rule: PS-001 The @Observable macro provides 6x faster list updates (WWDC 2025), cleaner syntax, and precise property-level invalidation. This is the modern pattern.
Issue 3: Missing accessibility labels on text elements (Line 34-37)
// CURRENT - No context for VoiceOver
Text(event.title)
.font(.system(size: 18, weight: .bold))
// POLISHED
Text(event.title)
.font(.headline)
.accessibilityElement(children: .combine)
Severity: ๐ด Critical | Rule: PS-044 VoiceOver users hear uncontextualized text. Add semantic labels.
Issue 4: Hardcoded font sizes instead of text styles (Line 34)
// CURRENT - Won't scale with Dynamic Type
.font(.system(size: 18, weight: .bold))
// POLISHED - Scales automatically
.font(.headline)
Severity: ๐ Important | Rule: PS-056 Hardcoded sizes fail for users with accessibility text scaling enabled. Text styles automatically adapt.
Issue 5: Using VStack for potentially long list (Line 26)
// CURRENT - Renders ALL items at once (poor performance)
ScrollView {
VStack {
ForEach(viewModel.events) { event in
EventRow(event: event)
}
}
}
// POLISHED - Renders only visible items
List(viewModel.events) { event in
EventRow(event: event)
}
Severity: ๐ Important | Rule: PS-032 VStack renders all 1000 events even if only 5 are visible. List uses lazy rendering. WWDC 2025 shows 16x performance improvement with List.
Issue 6: Using main queue dispatch instead of async/await (Line 15)
// CURRENT - Outdated concurrency pattern
DispatchQueue.main.async {
self.isLoading = false
}
// POLISHED - Modern Swift Concurrency
@MainActor
final class EventViewModel {
func loadEvents() async {
isLoading = true
events = try await networkService.fetchEvents()
isLoading = false
}
}
Severity: ๐ Important | Rule: PS-077 @MainActor eliminates manual main queue dispatch. Cleaner, safer, faster.
Issue 7: Using NavigationView (deprecated) (Line 23)
// CURRENT (iOS 16)
NavigationView {
// content
}
// POLISHED (iOS 16+, recommended iOS 18)
NavigationStack(path: $path) {
// content
.navigationDestination(for: Route.self) { route in
// handle routes
}
}
Severity: ๐ก Warning | Rule: PS-009 NavigationView is deprecated. NavigationStack offers type-safe routing and better performance.
Enhancement 1: Apply Liquid Glass Design (iOS 26)
// iOS 26 - Solarium Design System
EventRow(event: event)
.glassEffect() // New iOS 26 feature
The Solarium project brings visionOS-inspired translucency to iOS 26, creating an airier, more modern look.
Enhancement 2: Add gesture-driven animations
// iOS 18 - Physics-based motion
@State private var isExpanded = false
var body: some View {
EventRow()
.onTapGesture {
withAnimation(.spring(response: 0.35, dampingFraction: 0.8)) {
isExpanded.toggle()
}
}
}
Spring animations feel natural. WWDC 2025 emphasizes gesture-velocity tracking for fluid interactions.
@Observable Pattern (iOS 18+)
@Observable
final class EventViewModel {
var events: [Event] = []
var isLoading = false
var error: String?
@MainActor
func loadEvents() async {
isLoading = true
error = nil
do {
events = try await networkService.fetchEvents()
} catch {
error = error.localizedDescription
}
isLoading = false
}
}
struct EventListView: View {
@State var viewModel = EventViewModel()
var body: some View {
List(viewModel.events) { event in
EventRow(event: event)
}
.navigationTitle("Events")
.task {
await viewModel.loadEvents()
}
}
}
This eliminates @Published, uses @MainActor properly, leverages .task for async, and uses List for performance.
---
## Resources & References
**WWDC 2025 Guidance**
- [Catch up on accessibility in SwiftUI - WWDC24](https://developer.apple.com/videos/play/wwdc2024/10073/)
- [Optimize SwiftUI performance with Instruments - WWDC25](https://developer.apple.com/videos/play/wwdc2025/306/)
- [Build a SwiftUI app with the new design - WWDC25](https://developer.apple.com/videos/play/wwdc2025/323/)
**Apple Documentation**
- [Migrating from ObservableObject to @Observable](https://developer.apple.com/documentation/swiftui/migrating-from-the-observable-object-protocol-to-the-observable-macro)
- [Understanding and improving SwiftUI performance](https://developer.apple.com/documentation/Xcode/understanding-and-improving-swiftui-performance)
- [Accessibility modifiers](https://developer.apple.com/documentation/swiftui/view-accessibility)
- [Applying Liquid Glass to custom views](https://developer.apple.com/documentation/SwiftUI/Applying-Liquid-Glass-to-custom-views)
**Modern Patterns & Best Practices**
- [Modern SwiftUI Navigation: Best Practices for 2025 Apps](https://medium.com/@dinaga119/mastering-navigation-in-swiftui-the-2025-guide-to-clean-scalable-routing-bbcb6dbce929)
- [Modern MVVM in SwiftUI 2025: Clean Architecture](https://medium.com/@minalkewat/modern-mvvm-in-swiftui-2025-the-clean-architecture-youve-been-waiting-for-72a7d576648e)
- [24 SwiftUI Performance Tips Every iOS Developer Should Know (2025)](https://medium.com/@ravisolankice12/24-swiftui-performance-tips-every-ios-developer-should-know-2025-edition-723340d9bd79)
- [SwiftUI Animations 2025: Physics, Gestures & Advanced Techniques](https://medium.com/@bhumibhuva18/swiftui-animations-in-2025-beyond-basic-transitions-f63db40c7c46)
**Accessibility Excellence**
- [CVS Health iOS SwiftUI Accessibility Techniques](https://github.com/cvs-health/ios-swiftui-accessibility-techniques)
- [WCAG Applicability to Native iOS Apps](https://knowbility.org/programs/john-slatin-accessu-2025/swiftui-accessibility-techniques-for-native-ios-apps/)
- [AccessLint โ iOS Accessibility Analysis at Build Time](https://accesslint.app/)
**Design System & visionOS Inspiration**
- [visionOS Design Patterns & iOS 26 Design Overhaul](https://applemagazine.com/apples-ios-26-to-introduce-visionos-inspired/)
- [Liquid Glass & Solarium Design System - Apple](https://www.apple.com/newsroom/2025/06/apple-introduces-a-delightful-and-elegant-new-software-design/)
---
## Implementation Strategy
1. **Phase 1 - State (Critical)**: Migrate to @Observable + @MainActor
2. **Phase 2 - Performance**: Replace VStack with List, optimize view bodies
3. **Phase 3 - Accessibility**: Add labels, test with VoiceOver
4. **Phase 4 - Design**: Apply Liquid Glass, modern colors, animations
5. **Phase 5 - Polish**: Gesture interactions, physics-based animations
---
**Key Insight**: iOS 18+ code using @Observable and @MainActor is dramatically simpler, faster, and more accessible than pre-iOS 18 patterns. This polish command helps you leverage 2025's best practices.