home / skills / hoangnguyen0403 / agent-skills-standard / persistence

persistence skill

/skills/ios/persistence

This skill enforces iOS persistence best practices for SwiftData and Core Data, guiding safe threading, migrations, and efficient data access.

npx playbooks add skill hoangnguyen0403/agent-skills-standard --skill persistence

Review the files below or copy the command above to add this skill to your agents.

Files (2)
SKILL.md
1.8 KB
---
name: iOS Persistence
description: Standards for SwiftData, Core Data, and Local Storage.
metadata:
  labels: [ios, persistence, swiftdata, coredata, sqlite]
  triggers:
    files: ['**/*.xcdatamodeld', '**/*Model.swift']
    keywords:
      [
        PersistentContainer,
        FetchRequest,
        ManagedObject,
        Query,
        ModelContainer,
        Repository,
      ]
---

# iOS Persistence Standards

## **Priority: P0**

## Implementation Guidelines

### SwiftData (iOS 17+)

- **Models**: Use `@Model` macro for pure Swift classes.
- **Container**: Use `ModelContainer` for schema management. Inject into the environment for SwiftUI apps.
- **Queries**: Use `@Query` for declarative data fetching in Views.

### Core Data (Standard)

- **Persistent Stack**: Initialize `NSPersistentContainer` in a dedicated `PersistenceController`.
- **Context Management**: Use `viewContext` for UI tasks and `newBackgroundContext()` for heavy imports to avoid blocking the main thread.
- **FetchedResultsController**: Use `NSFetchedResultsController` for efficient list management with change tracking.

### Best Practices

- **Migration**: Always perform lightweight migrations for minor schema changes. Use versioned models for complex migrations.
- **Threading**: Managed objects are not thread-safe. Always access them on the context's queue (e.g., `perform { ... }`).
- **Batching**: Use `NSBatchUpdateRequest` or `NSBatchDeleteRequest` for large datasets.

## Anti-Patterns

- **Main Thread Blocking**: `**No heavy I/O on ViewContext**: Use private background contexts.`
- **Manual String Keys**: `**No string-based predicates**: Use KeyPaths or generated helpers.`
- **Missing Merge Policies**: `**No merge strategy**: Explicitly set mergePolicy (e.g., mergeByPropertyObjectTrump).`

## References

- [SwiftData & Core Data Implementation](references/implementation.md)

Overview

This skill documents iOS persistence standards for SwiftData, Core Data, and local storage patterns. It explains recommended implementations, common anti-patterns, and practical steps to keep data layers reliable, performant, and thread-safe. The guidance targets app architects and engineers building SwiftUI and UIKit apps across iOS versions.

How this skill works

The skill outlines model definitions, container setup, and query patterns for SwiftData (iOS 17+) and the persistent stack, contexts, and controllers for Core Data. It describes when to use view contexts versus background contexts, how to perform migrations and batch operations, and which APIs to prefer for efficient list updates and change tracking. Anti-patterns and merge policy advice reduce data corruption and UI stalls.

When to use it

  • New SwiftUI apps on iOS 17+ that can adopt SwiftData and @Model annotations.
  • Existing apps using Core Data that require robust context and migration management.
  • Features that import large datasets or perform heavy I/O and must avoid blocking the main thread.
  • List-driven UIs that need efficient change tracking and incremental updates.
  • Apps requiring safe background writes, conflict resolution, or batch cleanup tasks.

Best practices

  • Use @Model and ModelContainer for SwiftData; inject the container into the SwiftUI environment.
  • Initialize NSPersistentContainer in a dedicated PersistenceController; separate viewContext and background contexts.
  • Run heavy imports and batch operations on private contexts; call context.perform { } to access managed objects on their queue.
  • Prefer NSFetchedResultsController for UITableView/UICollectionView list syncing and @Query for SwiftUI Views.
  • Always define migration strategy: lightweight migrations for minor changes and versioned models for complex schema changes.
  • Avoid string-based predicates and manual keys; prefer KeyPaths or generated helpers and set explicit mergePolicy to resolve conflicts.

Example use cases

  • A SwiftUI app using SwiftData for lightweight local storage with declarative @Query lists.
  • A legacy Core Data app adding a large CSV import executed on a background context with NSBatchInsert.
  • A chat app that needs conflict resolution and merge policies when syncing remote updates into the local store.
  • A data-heavy feed that uses NSFetchedResultsController to keep a table view responsive during frequent updates.
  • Migration workflows where schema changes are first attempted as lightweight migrations and escalated to versioned migrations when needed.

FAQ

When should I choose SwiftData over Core Data?

Prefer SwiftData for new SwiftUI-first apps on iOS 17+ for simpler models and @Query integration; keep Core Data for mature projects with existing models or when you need advanced Cocoa interoperability.

How do I avoid UI freezes during large imports?

Perform imports on a private background context or use NSBatchInsert/NSBatchUpdate/NSBatchDelete. Never run heavy I/O on viewContext or the main thread.

What mergePolicy should I use?

Set an explicit mergePolicy (for example, mergeByPropertyObjectTrump) appropriate to your conflict model, and test resolution paths under concurrent writes.