Docs Menu

Read & Write Data - Swift SDK

On this page

The examples on this page use the following models:

A filter selects a subset of results based on the value(s) of one or more object properties. Realm Database provides a full-featured query engine that you can use to define filters.

Tip
Filter on Related and Embedded Object Properties

To filter a query based on a property of an embedded object or a related object, use dot-notation as if it were in a regular, nested object.

The types in your predicate must match the types of the properties. Avoid comparing ObjectId properties to strings, as Realm Database does not automatically convert strings to ObjectIds.

A sort operation allows you to configure the order in which Realm Database returns queried objects. You can sort based on one or more properties of the objects in the results collection. Realm Database only guarantees a consistent order of results if you explicitly sort them.

Tip
Sort on Related and Embedded Object Properties

To sort a query based on a property of an embedded object or a related object, use dot-notation as if it were in a regular, nested object.

Note

String sorting and case-insensitive queries are only supported for character sets in 'Latin Basic', 'Latin Supplement', 'Latin Extended A', and 'Latin Extended B' (UTF-8 range 0-591).

You can query through a relationship the same way you would access a member of a regular Swift or Objective-C object.

You can query through an inverse relationship the same way you would access a member of a regular Swift or Objective-C object.

You can use Realm's aggregation operators for sophisticated queries against list properties.

Because results are lazily evaluated, you can chain several queries together. Unlike traditional databases, this does not require a separate trip to the database for each successive query.

Example

To get a result set for tan dogs, and tan dogs whose names start with 'B', chain two queries like this:

You can initialize an object by passing an initializer value to Object.init(value:). The initializer value can be a key-value coding compliant object, a dictionary, or an array containing one element for each managed property.

Note

When using an array as an initializer value, you must include all properties in the same order as they are defined in the model.

You can even initialize related or embedded objects by nesting initializer values:

Realm does not directly support JSON, but you can use JSONSerialization.jsonObject(with:options:) to convert JSON into a value that you can pass to Realm.create(_:value:update:).

Nested objects or arrays in the JSON map to to-one or to-many relationships.

The JSON property names and types must match the destination object schema exactly. For example:

  • float properties must be initialized with float-backed NSNumbers.
  • Date and Data properties cannot be inferred from strings. Convert them to the appropriate type before passing to Realm.create(_:value:update:).
  • Required properties cannot be null or missing in the JSON.

Realm ignores any properties in the JSON not defined in the object schema.

Tip

If your JSON schema doesn't exactly align with your Realm objects, consider using a third-party framework to transform your JSON. There are many model mapping frameworks that work with Realm. See a partial list in the realm-swift repository.

Important

The create methods do not support handling cyclical object graphs. Do not pass in an object containing relationships involving objects that refer back to their parents, either directly or indirectly.

New in version 10.26.0.

You can add, modify, or delete objects in the background using writeAsync.

With async write, you don't need to pass a thread-safe reference or frozen objects across threads. Instead, call realm.writeAsync. You can provide a completion block for the method to execute on the source thread after the write completes or fails.

Things to consider when performing background writes:

  • Async writes block closing or invalidating the realm
  • You can explicitly commit or cancel transactions
let realm = try! Realm()
// Query for a specific person object on the main thread
let people = realm.objects(Person.self)
let thisPerson = people.where {
$0.name == "Dachary"
}.first
// Perform an async write to add dogs to that person's dog list.
// No need to pass a thread-safe reference or frozen object.
realm.writeAsync {
thisPerson?.dogs.append(objectsIn: [
Dog(value: ["name": "Ben", "age": 13]),
Dog(value: ["name": "Lita", "age": 9]),
Dog(value: ["name": "Maui", "age": 1])
])
} onComplete: { _ in
// Confirm the three dogs were successfully added to the person's dogs list
XCTAssertEqual(thisPerson!.dogs.count, 3)
// Query for one of the dogs we added and see that it is present
let dogs = realm.objects(Dog.self)
let benDogs = dogs.where {
$0.name == "Ben"
}
XCTAssertEqual(benDogs.count, 1)
}

The SDK provides a Bool to signal whether the realm is currently performing an async write. The isPerformingAsynchronousWriteOperations variable becomes true after a call to one of:

  • writeAsync
  • beginAsyncWrite
  • commitAsyncWrite

It remains true until all scheduled async write operations have completed. While this is true, this blocks closing or invalidating the realm.

To complete an async write, you or the SDK must call either:

When you use the writeAsync method, the SDK handles committing or canceling the transaction. This provides the convenience of the async write without the need to manually keep state tied to the scope of the object. However, while in the writeAsync block, you can explicitly call commitAsyncWrite or cancelAsyncWrite. If you return without calling one of these methods, writeAsync either:

  • Commits the write after executing the instructions in the write block
  • Returns an error

In either case, this completes the writeAsync operation.

For more control over when to commit or cancel the async write transaction, use the beginAsyncWrite method. When you use this method, you must explicitly commit the transactions. Returning without committing an async write cancels the transaction. beginAsyncWrite returns an ID that you can pass to cancelAsyncWrite.

commitAsyncWrite asynchronously commits a write transaction. This is the step that persists the data to the realm. commitAsyncWrite can take an onComplete block. . This block executes on the source thread once the commit completes or fails with an error.

Calling commitAsyncWrite immediately returns. This allows the caller to proceed while the SDK performs the I/O on a background thread. This method returns an ID that you can pass to cancelAsyncWrite. This cancels the pending invocation of the completion block. It does not cancel the commit itself.

You can group sequential calls to commitAsyncWrite. Batching these calls improves write performance; particularly when the batched transactions are small. To permit grouping transactions, set the isGroupingAllowed parameter to true.

You can call cancelAsyncWrite on either beginAsyncWrite or commitAsyncWrite. When you call it on beginAsyncWrite, this cancels the entire write transaction. When you call it on commitAsyncWrite, this cancels only an onComplete block you may have passed to commitAsyncWrite. It does not cancel the commit itself. You need the ID of the beginAsyncWrite or the commitAsyncWrite you want to cancel.

You can modify properties of a Realm object inside of a write transaction in the same way that you would update any other Swift or Objective-C object.

Tip
Update Related and Embedded Objects

To update a property of an embedded object or a related object, modify the property with dot-notation or bracket-notation as if it were in a regular, nested object.

Object, Result, and List all conform to key-value coding. This can be useful when you need to determine which property to update at runtime.

Applying KVC to a collection is a great way to update objects in bulk. Avoid the overhead of iterating over a collection while creating accessors for every item.

let realm = try! Realm()
let allDogs = realm.objects(Dog.self)
try! realm.write {
allDogs.first?.setValue("Sparky", forKey: "name")
// Move the dogs to Toronto for vacation
allDogs.setValue("Toronto", forKey: "currentCity")
}
Tip

You can also add values for embedded objects or relationships this way. See Initialize Objects with a Value.

An upsert either inserts or updates an object depending on whether the object already exists. Upserts require the data model to have a primary key.

You can also partially update an object by passing the primary key and a subset of the values to update:

Important
Do not use objects after delete

You cannot access or modify an object after you have deleted it from a realm. If you try to use a deleted object, Realm Database throws an error.

←  Configure & Open a Realm - Swift SDKFilter Data - Swift SDK →
Give Feedback
© 2022 MongoDB, Inc.

About

  • Careers
  • Investor Relations
  • Legal Notices
  • Privacy Notices
  • Security Information
  • Trust Center
© 2022 MongoDB, Inc.