This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
mobilehigh PriorityID: swiftdata-modern-persistence

SwiftData iOS 17+ Modern Model Persistence & Concurrency Standard

Production persistence architecture for iOS 17/18 and macOS using SwiftData. Replaces verbose CoreData boilerplate with declarative @Model macros, type-safe #Predicate queries, @Query SwiftUI property wrappers, and ModelActor background isolation.

Prohibited Anti-Pattern: AI scaffolds legacy CoreData .xcdatamodeld and passes NSManagedObject instances across Swift concurrency boundaries.

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: SwiftData iOS 17+ Modern Model Persistence & Concurrency Standard - Production persistence architecture for iOS 17/18 and macOS using SwiftData. Replaces verbose CoreData boilerplate with declarative @Model macros, type-safe #Predicate queries, @Query SwiftUI property wrappers, and ModelActor background isolation.
globs: **/*Model*.swift, **/*DataStore*.swift, App/**/*.swift
alwaysApply: false
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/swiftdata-modern-persistence"
---

# SwiftData iOS 17+ Modern Model Persistence & Concurrency Standard

> **Severity**: HIGH | **Category**: mobile
> **Anti-Pattern Warning**: AI scaffolds legacy CoreData .xcdatamodeld and passes NSManagedObject instances across Swift concurrency boundaries.

## System Constraints
You are an iOS and Swift architecture specialist. In modern iOS 17+ projects, NEVER scaffold legacy CoreData .xcdatamodeld files or pass NSManagedObject across unstructured Task boundaries. Always use SwiftData with declarative @Model classes, type-safe #Predicate macros, and ModelActor for background thread ingestion.

## Strict Guidelines
- Annotate domain entities with @Model; define unique constraints using @Attribute(.unique) on primary key fields.
- Use #Predicate with type-safe keypath expressions for database filtering rather than NSPredicate format strings.
- Use @Query in SwiftUI views for automatic reactive database observation and instant UI synchronization.
- Execute background data synchronization exclusively inside a custom actor conforming to ModelActor with its own dedicated ModelContext.

## Bad vs Good Implementations
### Declarative SwiftData @Model with Type-Safe Predicate vs Legacy CoreData

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: String-based NSPredicate fails at runtime on typos and CoreData models lack native Swift 6 sendable concurrency safety.
```swift
// ANTI-PATTERN: Legacy CoreData with dangerous string-formatted predicates and unsafe object passing
let request = NSFetchRequest<NSManagedObject>(entityName: "Customer")
request.predicate = NSPredicate(format: "email == %@", userEmail) // Runtime crash if typo in property name!
let results = try context.fetch(request)
```

#### Production Standard (Correct)
> **Standard**: The #Predicate macro verifies types and property names at compile time, while @Query provides automatic differential UI updates.
```swift
// PRODUCTION STANDARD: SwiftData Declarative @Model with Compile-Time #Predicate
import SwiftUI
import SwiftData

@Model
final class Customer {
    @Attribute(.unique) var id: UUID
    var name: String
    var email: String
    var isVip: Bool
    var createdAt: Date
    
    init(id: UUID = UUID(), name: String, email: String, isVip: Bool = false) {
        self.id = id
        self.name = name
        self.email = email
        self.isVip = isVip
        self.createdAt = Date()
    }
}

struct CustomerListView: View {
    @Environment(\.modelContext) private var modelContext
    // Declarative live auto-updating query
    @Query(filter: #Predicate<Customer> { $0.isVip == true }, sort: \Customer.createdAt, order: .reverse)
    private var vipCustomers: [Customer]
    
    var body: some View {
        List(vipCustomers) {
            Text($0.name).font(.headline)
        }
    }
}
```

### Background Ingestion with ModelActor

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Calling insert() from arbitrary background threads violates context thread confinement and crashes with fatal data corruption.
```swift
// ANTI-PATTERN: Mutating model context from arbitrary Task { ... }
Task {
  let item = Customer(name: "Bob", email: "[email protected]")
  mainContext.insert(item) // CRASH: CoreData/SwiftData multi-thread data race!
}
```

#### Production Standard (Correct)
> **Standard**: Swift 6 compiler guarantees actor-isolated serialization with a private thread-safe ModelContext.
```swift
// PRODUCTION STANDARD: Dedicated ModelActor for Concurrency-Safe Ingestion
@ModelActor
actor BackgroundCustomerSyncer {
    func importRemoteCustomers(_ records: [CustomerDTO]) throws {
        for record in records {
            let customer = Customer(name: record.name, email: record.email)
            modelContext.insert(customer)
        }
        try modelContext.save()
    }
}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: SwiftData iOS 17+ Modern Model Persistence & Concurrency Standard

SwiftData iOS 17+ Modern Model Persistence & Concurrency Standard defines an industrial-grade behavioral standard for mobile engineering. Production persistence architecture for iOS 17/18 and macOS using SwiftData. Replaces verbose CoreData boilerplate with declarative @Model macros, type-safe #Predicate queries, @Query SwiftUI property wrappers, and ModelActor background isolation. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: AI scaffolds legacy CoreData .xcdatamodeld and passes NSManagedObject instances across Swift concurrency boundaries. Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftAI scaffolds legacy CoreData .xcdatamodeld and passes NSManagedObject instances across Swift concurrency boundaries.High
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Annotate domain entities with @Model

Annotate domain entities with @Model; define unique constraints using @Attribute(.unique) on primary key fields.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Use #Predicate with type-safe keypath expressions for database filtering rather than NSPredicate format strings.

Use #Predicate with type-safe keypath expressions for database filtering rather than NSPredicate format strings.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Use @Query in SwiftUI views for automatic reactive database observation and instant UI synchronization.

Use @Query in SwiftUI views for automatic reactive database observation and instant UI synchronization.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Execute background data synchronization exclusively inside a custom actor conforming to ModelActor with its own dedicated ModelContext.

Execute background data synchronization exclusively inside a custom actor conforming to ModelActor with its own dedicated ModelContext.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is SwiftData iOS 17+ Modern Model Persistence & Concurrency Standard critical for AI coding assistants?

Production persistence architecture for iOS 17/18 and macOS using SwiftData. Replaces verbose CoreData boilerplate with declarative @Model macros, type-safe #Predicate queries, @Query SwiftUI property wrappers, and ModelActor background isolation. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (AI scaffolds legacy CoreData .xcdatamodeld and passes NSManagedObject instances across Swift concurrency boundaries.) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

Related MOBILE Rules

View all rules →
1 Rule in Stack

SwiftData