Technical

Why We Chose SwiftData Over Core Data for QuietClip

SwiftData and Core Data both persist data on Apple platforms. Here's why SwiftData was the right choice for a clipboard manager — and where Core Data still has an edge.

Why We Chose SwiftData Over Core Data for QuietClip
Technical | | 5 min read

When we started building QuietClip, one of the first architectural decisions was how to persist clipboard history. A clipboard manager accumulates data constantly — every copy adds a row — and needs to query it fast (the search panel has to feel instant). We needed a real database, not UserDefaults or flat files.

The choice came down to Core Data and SwiftData. We went with SwiftData. Here’s why — and where we think Core Data is still the better option.

Why we needed persistence

Clipboard managers have specific persistence requirements:

  • High write frequency — new items arrive every few seconds during active use
  • Fast reads with filtering — the user types a search query and results must appear instantly
  • Mixed data types — text strings, image data (as file references), metadata
  • Bounded growth — the database must enforce a maximum item count
  • Reliability — losing clipboard history defeats the entire purpose

Both Core Data and SwiftData, backed by SQLite, handle all of this. The question was which one made the codebase simpler.

SwiftData advantages

The difference in model definition is striking. Here’s a simplified clipboard item in Core Data versus SwiftData:

Core Data requires an .xcdatamodeld file in Xcode’s visual editor, plus a generated NSManagedObject subclass. Changing a property means updating the model editor, regenerating code, and potentially writing a migration mapping.

SwiftData is just Swift:

@Model
final class ClipItem {
    var content: String
    var imageURL: String?
    var sourceApp: String?
    var copiedAt: Date
    var isPinned: Bool

    init(content: String, copiedAt: Date = .now) {
        self.content = content
        self.copiedAt = copiedAt
        self.isPinned = false
    }
}

That’s the entire model definition. The schema, the storage, the SwiftUI integration — it all flows from the @Model macro.

With SwiftData, the model IS the schema. There’s no separate definition to keep in sync, no code generation step, no visual editor. You write Swift, and it works.

Where Core Data still wins

SwiftData isn’t universally better. Core Data has real advantages in certain scenarios:

Migration control. Core Data’s heavyweight migration with mapping models gives you fine-grained control over how data transforms between schema versions. SwiftData’s lightweight migration handles adding and removing properties automatically, but complex transformations (renaming a property, splitting a field into two) can be harder.

Mature escape hatches. Core Data lets you drop down to raw SQL via NSPersistentStoreCoordinator, use batch operations (NSBatchDeleteRequest, NSBatchInsertRequest), and access the SQLite store directly. SwiftData’s surface area is smaller — intentionally — but that means fewer options when you hit an edge case.

Deployment target. Core Data runs on every Apple OS version. SwiftData requires macOS 14+, iOS 17+. If you need to support older systems, Core Data is your only option.

Tradeoff

Migration complexity

For QuietClip’s simple data model — a flat table of clipboard items with text, image references, and metadata — SwiftData’s automatic lightweight migration handles every change we’ve needed. Adding a new property? SwiftData migrates the store automatically. But if we needed to restructure the schema significantly, Core Data’s mapping models would give us more control.

Our data model

QuietClip’s data model is deliberately simple. Each clipboard entry stores:

  • The text content (for text items) or a file path (for images)
  • The source application’s bundle identifier
  • A timestamp
  • A pinned flag
  • The pasteboard type metadata

This flat structure is ideal for SwiftData. No relationships, no complex graphs, no need for Core Data’s more advanced features like fetched properties or derived attributes.

Querying is handled entirely with @Query in SwiftUI:

@Query(sort: \ClipItem.copiedAt, order: .reverse)
private var items: [ClipItem]

For search, #Predicate replaces NSPredicate with type-safe, compile-time-checked filtering:

let searchPredicate = #Predicate<ClipItem> { item in
    item.content.localizedStandardContains(searchText)
}

No stringly-typed key paths. No runtime crashes from typos in predicate format strings.

The decision

For a new macOS app targeting macOS 14+ with a simple data model and a SwiftUI interface, SwiftData was the clear choice. It eliminated hundreds of lines of boilerplate, integrated naturally with our SwiftUI views, and made the codebase genuinely easier to understand.

Bottom line

If your app targets macOS 14+, has a straightforward data model, and uses SwiftUI — choose SwiftData. You’ll write less code, maintain less infrastructure, and ship faster. Core Data is still the right choice for complex schemas, legacy OS support, or apps that need granular migration control.

The best persistence layer is the one that disappears into the background. With SwiftData, we spend our time on clipboard features, not database plumbing. That’s exactly what we wanted.

Next step

Built on SwiftData. Built to last.

QuietClip uses SwiftData for fast, reliable clipboard history. Up to 1,000 items, searchable instantly, stored locally. Free to start, $8.99 once for Pro.

Download QuietClip Free

Frequently asked questions

Is SwiftData production-ready?
Yes, as of macOS 14 and later. Early versions (macOS 14.0-14.2) had some rough edges with migration and concurrency, but subsequent releases have been stable. QuietClip has shipped on SwiftData since its first version with no data loss issues.
Can SwiftData and Core Data coexist in the same app?
Yes. They can even share the same SQLite store using NSPersistentContainer alongside ModelContainer. This is useful for gradual migration, but adds complexity. For new apps, pick one.
Does SwiftData support CloudKit sync?
SwiftData supports CloudKit sync through ModelConfiguration, similar to NSPersistentCloudKitContainer. QuietClip doesn't use it — local-only storage is a deliberate privacy choice — but it's available if your app needs it.

Try QuietClip free

A privacy-first clipboard manager for macOS. Your data stays on your device, always.

Download for macOS

Related reads