Read & Write Data - Swift SDK
On this page
- About These Examples
- Read Operations
- Find a Specific Object by Primary Key
- Query All Objects of a Given Type
- Filter Queries Based on Object Properties
- Filter on Object ID Properties
- Sort Query Results
- Query a Relationship
- Query an Inverse Relationship
- Aggregate Data
- Chain Queries
- Write Operations
- Create a New Object
- Initialize Objects with a Value
- Create an Object with JSON
- Copy an Object to Another Realm
- Perform a Background Write
- Modify an Object
- Update Properties with Key-value Coding
- Upsert an Object
- Delete an Object
- Delete Multiple Objects
- Delete All Objects of a Specific Type
- Delete All Objects in a Realm
About These Examples
The examples on this page use the following models:
Read Operations
Find a Specific Object by Primary Key
Query All Objects of a Given Type
Filter Queries Based on Object Properties
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.
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.
Filter on Object ID Properties
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.
Sort Query Results
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.
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.
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).
Query a Relationship
You can query through a relationship the same way you would access a member of a regular Swift or Objective-C object.
Query an Inverse Relationship
You can query through an inverse relationship the same way you would access a member of a regular Swift or Objective-C object.
Aggregate Data
You can use Realm's aggregation operators for sophisticated queries against list properties.
Chain Queries
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.
To get a result set for tan dogs, and tan dogs whose names start with 'B', chain two queries like this:
Write Operations
Create a New Object
Initialize Objects with a Value
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.
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:
Create an Object with JSON
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-backedNSNumbers
.Date
andData
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.
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.
Copy an Object to Another Realm
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.
Perform a Background Write
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) }
Wait for Async Writes to Complete
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.
Commit or Cancel an Async Write
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.
Modify an Object
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.
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.
Update Properties with Key-value Coding
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") }
You can also add values for embedded objects or relationships this way. See Initialize Objects with a Value.
Upsert an Object
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:
Delete an Object
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.