SwiftUI Cursor Rules: Apple UI Framework Guide

Cursor rules for SwiftUI development covering declarative UI patterns, state management, data flow, animations, and platform integration for iOS/macOS applications.

October 5, 2025by PromptGenius Team
swiftuicursor-rulesiosappledeclarative-ui

Overview

SwiftUI is Apple's modern, declarative UI framework for building fluid, native user interfaces across iOS, macOS, watchOS, and tvOS. These cursor rules enforce strict state management (@State, @Binding), robust MVVM architectural patterns, and accessibility best practices to help AI assistants generate clean, responsive interfaces. Whether you're building complex data-driven apps or intricate animations, these rules ensure your views are perfectly aligned with Apple's design and platform conventions.

Note:

Enforces @State/@Binding patterns, MVVM architecture, accessibility labels, and SwiftUI animation best practices.

Rules Configuration

---
description: Enforces best practices for SwiftUI development, focusing on declarative UI, state management, and MVVM architecture. Provides comprehensive guidelines for writing clean, accessible native UIs with proper context.
globs: **/*.swift
---
# SwiftUI Best Practices

You are an expert in SwiftUI development and Apple platform technologies.
You understand modern SwiftUI development practices, architectural patterns, and the importance of providing complete context in code generation.

### Context-Aware Code Generation
- Provide complete view context including state property wrappers, bindings, and environment objects
- Include relevant configuration (Info.plist, asset catalogs) when generating project code
- Generate complete view signatures with proper property wrappers and body declarations
- Include Swift documentation comments explaining view purpose, state, and interactions

### State Management
- Use @State for local view state owned by the view
- Use @Binding for two-way connections to state owned by a parent view
- Use @ObservedObject or @StateObject for reference type model data
- Use @EnvironmentObject for shared dependency injection across the view hierarchy
- Use @Published in ObservableObject ViewModels to trigger UI updates
- Prefer @State over @ObservedObject for simple value-type state

### MVVM Architecture
- Keep views declarative: they describe UI based on ViewModel state
- Place business logic in ViewModels, never in View structs
- Use ObservableObject with @Published for ViewModel state
- Inject dependencies via @EnvironmentObject or initializer injection
- Use separate model files for data types and API logic

### View Composition & Modifiers
- Break complex views into smaller, reusable subviews
- Extract repeated modifier chains into custom ViewModifier types
- Prefer ViewBuilder with @ViewBuilder for conditional content
- Use Group and AnyView sparingly; prefer conditional view extraction
- Apply consistent padding, frame, and alignment modifiers

### Accessibility
- Add .accessibilityLabel() and .accessibilityHint() to interactive elements
- Use .accessibilityAddTraits(.isButton) for tappable elements
- Support Dynamic Type with scalable fonts (.body, .title, etc.)
- Test with VoiceOver for proper element ordering and navigation

### Testing & Quality
- Write unit tests for ViewModel logic using XCTest
- Use ViewInspector or Xcode Previews for view rendering tests
- Test navigation flows and state transitions
- Run SwiftLint for consistent code style across the team

Installation

Create swiftui.mdc in your project's .cursor/rules/ directory and paste the configuration above. Cursor and Windsurf both read .cursor/rules/ — Copilot users place it in .github/copilot-instructions.md instead.

Examples

// UserView.swift — MVVM pattern with @StateObject and @Published
import SwiftUI

class UserViewModel: ObservableObject {
    @Published var name = ""
    @Published var email = ""

    func save() { /* business logic */ }
}

struct UserView: View {
    @StateObject private var viewModel = UserViewModel()

    var body: some View {
        Form {
            TextField("Name", text: $viewModel.name)
            TextField("Email", text: $viewModel.email)
            Button("Save") { viewModel.save() }
        }
        .accessibilityLabel("User form")
    }
}
// CustomModifier.swift — Reusable view modifier pattern
import SwiftUI

struct CardStyle: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding()
            .background(Color(.systemBackground))
            .cornerRadius(12)
            .shadow(radius: 4)
    }
}

extension View {
    func cardStyle() -> some View {
        modifier(CardStyle())
    }
}