Find this interesting?

Get started with our free plan, which includes 1 subscriber-only episode of your choice, access to 73 free episodes with transcripts and code samples, and weekly updates from our newsletter.

Sign up for free →View plans and pricing

Today we are releasing SQLiteData 1.0, an alternative to SwiftData that provides familiar tool to build apps with complex persistence and query needs, with none of the gotchas, based on SQLite:

  • Model your data types as concisely as possible using everything Swift has to offer, such as structs and enums.

  • Perform type-safe and schema-safe queries to fetch your data in anyway you want.

  • Decode data from the database using a performant, custom SQLite decoder that is only a tiny bit slower than dealing directly with SQLite’s C functions.

  • Leverage property wrappers similar to SwiftData’s @Query that allow you to fetch data in SwiftUI views so that when the database changes the view automatically refreshes. These property wrappers even work outside of SwiftUI views, such as in @Observable models and even UIKit view controllers.

  • Direct support for CloudKit synchronization so that your users’ data is distributed across all of their devices.

  • Support for iCloud sharing, which allows your users to share a record (and all of its associated data) with another iCloud user.

  • Powered by SQLite, a battle tested technology that is over 25 years old and one of the most widely deployed pieces of software in history.

It accomplishes all of this (and more) in a lightweight and ergonomic API that is fully documented and comes with a wide variety of demo apps and case studies.

Using SQLiteData

SQLiteData allows you to model your domain types as concisely as possible, using all of the amazing tools that Swift gives us. This means you can use structs instead of classes, raw representable enums to model choices, and immutable lets for identifiers that should not change after instantiation:

import SQLiteData

@Table
struct Reminder: Identifiable {
  let id: UUID 
  var title = ""
  var isCompleted = false 
  var priority: Priority?
  
  enum Priority: Int {
    case low, medium, high
  }
}

After a little bit of work to prepare your SQLite database, you can immediately start fetching this data from the database using the @FetchAll property wrapper:

struct RemindersView: View {
  @FetchAll var reminders: [Reminder]
  var body: some View {
    ForEach(reminders) { reminder in
      Text(reminder.title)
    }
  }
}

Even better, you can describe the SQL query that powers this data directly inline with the property wrapper. For example, to sort incomplete reminders above completed ones you can do:

@FetchAll(Reminder.order(by: \.isCompleted)) 
var reminders

Or to fetch only high-priority reminders:

@FetchAll(Reminder.where { $0.priority.eq(Priority.high) }) 
var reminders

This barely scratches the surface of the kinds of queries you can build. Our library supports SQL joins, aggregates, common table expressions, and more. See the full docs of our StructuredQueries for more information on writing type-safe and schema-safe queries.

Example projects galore

SQLiteData comes with many, many example projects to show you the best practices of getting started, and how to solve the most common problems one comes across in apps with complex persistence and querying needs:

  • Case Studies
    Demonstrates how to solve some common application problems in a simplified environment, in both SwiftUI and UIKit. This includes animation, dynamic queries, database transactions, and more.

  • CloudKit Demo
    A simplified demo that shows how to synchronize a SQLite database to CloudKit and how to share records with other iCloud users. See our dedicated articles on CloudKit Synchronization and CloudKit Sharing for more information.

  • Reminders
    A rebuild of Apple’s Reminders app that uses a SQLite database to model the reminders, lists, and tags. It features many advanced queries, such as searching, stats aggregation, and multi-table joins. It also features CloudKit synchronization and sharing.

  • SyncUps
    This application is a faithful reconstruction of one of Apple’s more interesting sample projects called Scrumdinger, and it uses SQLite to persist its data for meetings. We have also added CloudKit synchronization so that all changes are automatically made available on all of the user’s devices.

If there are more examples or case studies you would like to see built, start a discussion!

Fully documented

The library comes fully documented with many articles exploring the more nuanced topics of data persistence and querying in complex applications:

If there is anything you feel is lacking from our documentation, please open a discussion and we can figure out how to better document the library!

Get started today

Give the library a spin today by cloning the repo, opening Examples.xcodeproj and running one of the many example apps. If you have any questions, feel free to start a discussion.

Get started with our free plan

Our free plan includes 1 subscriber-only episode of your choice, access to 73 free episodes with transcripts and code samples, and weekly updates from our newsletter.

View plans and pricing