Docs Menu
Docs Home
/ /
Atlas Device SDKs

Quick Start - Swift SDK

On this page

  • Import Realm
  • Define Your Object Model
  • Open a Realm
  • Create, Read, Update, and Delete Objects
  • Watch for Changes
  • Add Device Sync (Optional)
  • Prerequisites
  • Initialize the App
  • Authenticate a User
  • Open a Realm

This Quick Start demonstrates how to use Realm with the Realm Swift SDK. Before you begin, ensure you have Installed the Swift SDK.


See also:

If your app uses SwiftUI, check out the SwiftUI Quick Start.

Near the top of any Swift file that uses Realm, add the following import statement:

import RealmSwift

For a local-only realm, you can define your object model directly in code. In this quick start, you can remove ownerId unless you want to add the optional Device Sync.

class Todo: Object {
@Persisted(primaryKey: true) var _id: ObjectId
@Persisted var name: String = ""
@Persisted var status: String = ""
@Persisted var ownerId: String
convenience init(name: String, ownerId: String) {
self.init() = name
self.ownerId = ownerId

In a local-only realm, the simplest option to open a realm is to use the default realm with no configuration parameter:

// Open the local-only default realm
let realm = try! Realm()

You can also specify a Realm.Configuration parameter to open a realm at a specific file URL, in-memory, or with a subset of classes.

For more information, see: Configure and Open a Realm.

Once you have opened a realm, you can modify it and its objects in a write transaction block.

To create a new Todo object, instantiate the Todo class and add it to the realm in a write block:

let todo = Todo(name: "Do laundry", ownerId:
try! realm.write {

You can retrieve a live collection of all todos in the realm:

// Get all todos in the realm
let todos = realm.objects(Todo.self)

You can also filter that collection using where:

let todosInProgress = todos.where {
$0.status == "InProgress"
print("A list of all todos in progress: \(todosInProgress)")

To modify a todo, update its properties in a write transaction block:

// All modifications to a realm must happen in a write block.
let todoToUpdate = todos[0]
try! realm.write {
todoToUpdate.status = "InProgress"

Finally, you can delete a todo:

// All modifications to a realm must happen in a write block.
let todoToDelete = todos[0]
try! realm.write {
// Delete the Todo.

You can watch a realm, collection, or object for changes with the observe method.

// Retain notificationToken as long as you want to observe
let notificationToken = todos.observe { (changes) in
switch changes {
case .initial: break
// Results are now populated and can be accessed without blocking the UI
case .update(_, let deletions, let insertions, let modifications):
// Query results have changed.
print("Deleted indices: ", deletions)
print("Inserted indices: ", insertions)
print("Modified modifications: ", modifications)
case .error(let error):
// An error occurred while opening the Realm file on the background worker thread

Be sure to retain the notification token returned by observe as long as you want to continue observing. When you are done observing, invalidate the token to free the resources:

// Invalidate notification tokens when done observing

If you want to sync Realm data across devices, you can set up an Atlas App Services App and enable Device Sync. For more information on what you can do with App Services, see: App Services - Swift SDK.

Before you can sync Realm data, you must:

To use App Services features such as authentication and sync, access your App Services App using your App ID. You can find your App ID in the App Services UI.

let app = App(id: APP_ID) // Replace APP_ID with your Atlas App ID

In this quick start, you use anonymous authentication to log in users without requiring them to provide any identifying information. After authenticating the user, you can open a realm for that user.

do {
let user = try await app.login(credentials: Credentials.anonymous)
print("Successfully logged in user: \(user)")
await openSyncedRealm(user: user)
} catch {
print("Error logging in: \(error.localizedDescription)")

The Realm Swift SDK provides many additional ways to authenticate, register, and link users. For other authentication providers, see: Authenticate Users - Swift SDK

Once you have enabled Device Sync and authenticated a user, you can create a Configuration object and open the realm. You can then add a the Flexible Sync subscription that determines what data the realm can read and write.

Once you have a realm with a subscription, this example passes the realm and the user to another function where you can use the realm.


If your app accesses Realm in an async/await context, mark the code with @MainActor to avoid threading-related crashes.

// Opening a realm and accessing it must be done from the same thread.
// Marking this function as `@MainActor` avoids threading-related issues.
func openSyncedRealm(user: User) async {
do {
var config = user.flexibleSyncConfiguration()
// Pass object types to the Flexible Sync configuration
// as a temporary workaround for not being able to add a
// complete schema for a Flexible Sync app.
config.objectTypes = [Todo.self]
let realm = try await Realm(configuration: config, downloadBeforeOpen: .always)
// You must add at least one subscription to read and write from a Flexible Sync realm
let subscriptions = realm.subscriptions
try await subscriptions.update {
QuerySubscription<Todo> {
$0.ownerId ==
await useRealm(realm: realm, user: user)
} catch {
print("Error opening realm: \(error.localizedDescription)")

The syntax to read, write, and watch for changes on a synced realm is identical to the syntax for non-synced realms above. While you work with local data, a background thread efficiently integrates, uploads, and downloads changesets.

Every write transaction for a subscription set has a performance cost. If you need to make multiple updates to a Realm object during a session, consider keeping edited objects in memory until all changes are complete. This improves sync performance by only writing the complete and updated object to your realm instead of every change.

← Install the SDK for iOS, macOS, tvOS, and watchOS