Navigation

Quick Start

This page contains information to quickly get Realm Database integrated into your app. Before you begin, ensure you have:

Info With Circle IconCreated with Sketch.Note
Check Out the Tutorial

This page contains only the essential information that you need to set up a MongoDB Realm application. If you prefer to follow a guided tutorial that shows you step-by-step how to set up a working app, check out the iOS Tutorial where you'll build a mobile app that connects to the Task Tracker backend.

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

import RealmSwift

To use MongoDB Realm features such as authentication and sync, you must access your Realm app using your Realm app ID. You can find your Realm app ID in the Realm UI.

let app = App(id: YOUR_REALM_APP_ID) // Replace YOUR_REALM_APP_ID with your Realm app ID

If have not enabled Realm Sync or you enabled Sync with development mode in the Realm UI, you can define your object model directly in code.

Info With Circle IconCreated with Sketch.Note

If you have enabled Sync but turned off Developer Mode, you can copy and paste the object model definitions that Realm generated for you from the SDKs tab in the Realm UI. You must re-enable Developer Mode if you want to make changes to the object model definition from client side code. See Configure Your Data Model.

// QsTask is the Task model for this QuickStart
class QsTask: Object {
@objc dynamic var _id: ObjectId = ObjectId.generate()
// When configuring Sync, we selected `_partition` as the partition key.
// A partition key is only required if you are using Sync.
@objc dynamic var _partition: String = ""
@objc dynamic var name: String = ""
@objc dynamic var owner: String? = nil
@objc dynamic var status: String = ""
override static func primaryKey() -> String? {
return "_id"
}
convenience init(partition: String, name: String) {
self.init()
self._partition = partition;
self.name = name;
}
}

When you have enabled anonymous authentication in the Realm UI, users can immediately log into your app without providing any identifying information:

// Log in anonymously.
app.login(credentials: Credentials.anonymous) { (result) in
// Remember to dispatch back to the main thread in completion handlers
// if you want to do anything on the UI.
DispatchQueue.main.async {
switch result {
case .failure(let error):
print("Login failed: \(error)")
case .success(let user):
print("Login as \(user) succeeded!")
// Continue below
onLogin()
}
}
}

Realm provides many additional ways to authenticate, register, and link users.

Bulb IconTip

Once you have enabled Realm Sync and authenticated a user, you can open a realm asynchronously by calling asyncOpen, passing in the user's Configuration object, which includes the partition name. The following code demonstrates this:

let user = app.currentUser!
// The partition determines which subset of data to access.
let partitionValue = "myPartition"
// Get a sync configuration from the user object.
var configuration = user.configuration(partitionValue: partitionValue)
configuration.objectTypes = [QsTask.self]
// Open the realm asynchronously to ensure backend data is downloaded first.
Realm.asyncOpen(configuration: user.configuration(partitionValue: partitionValue)) { (result) in
switch result {
case .failure(let error):
print("Failed to open realm: \(error.localizedDescription)")
// Handle error...
case .success(let realm):
// realm successfully opened
}
}
Bulb IconTip
See Also:

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

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

let task = QsTask(partition: partitionValue, name: "Do laundry")
try! realm.write {
realm.add(task)
}

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

// Get all tasks in the realm
let tasks = realm.objects(QsTask.self)

You can also filter that collection using a filter:

let tasksInProgress = tasks.filter("status = %@", "InProgress")
print("A list of all tasks in progress: \(tasksInProgress)")

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

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

Finally, you can delete a task:

let taskToDelete = tasks[0]
// All modifications to a realm must happen in a write block.
try! realm.write {
// Delete the QsTask.
realm.delete(taskToDelete)
}

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

Info With Circle IconCreated with Sketch.Note

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.

// Retain notificationToken as long as you want to observe
let notificationToken = tasks.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
fatalError("\(error)")
}
}
// Later, when done observing
notificationToken.invalidate()

Once logged in, you can log out:

app.currentUser?.logOut() { (error) in
// Logged out or error occurred
}

Run the complete example by replacing the app ID with your Realm app ID and calling runExample().

import RealmSwift
// QsTask is the Task model for this QuickStart
class QsTask: Object {
@objc dynamic var _id: ObjectId = ObjectId.generate()
// When configuring Sync, we selected `_partition` as the partition key.
// A partition key is only required if you are using Sync.
@objc dynamic var _partition: String = ""
@objc dynamic var name: String = ""
@objc dynamic var owner: String?
@objc dynamic var status: String = ""
override static func primaryKey() -> String? {
return "_id"
}
convenience init(partition: String, name: String) {
self.init()
self._partition = partition
self.name = name
}
}
// Entrypoint. Call this to run the example.
func runExample() {
// Instantiate the app
let app = App(id: YOUR_REALM_APP_ID) // Replace YOUR_REALM_APP_ID with your Realm app ID
// Log in anonymously.
app.login(credentials: Credentials.anonymous) { (result) in
// Remember to dispatch back to the main thread in completion handlers
// if you want to do anything on the UI.
DispatchQueue.main.async {
switch result {
case .failure(let error):
print("Login failed: \(error)")
case .success(let user):
print("Login as \(user) succeeded!")
// Continue below
onLogin()
}
}
}
}
func onLogin() {
// Now logged in, do something with user
let user = app.currentUser!
// The partition determines which subset of data to access.
let partitionValue = "some partition value"
// Get a sync configuration from the user object.
var configuration = user.configuration(partitionValue: partitionValue)
configuration.objectTypes = [QsTask.self]
// Open the realm asynchronously to ensure backend data is downloaded first.
Realm.asyncOpen(configuration: configuration) { (result) in
switch result {
case .failure(let error):
print("Failed to open realm: \(error.localizedDescription)")
// Handle error...
case .success(let realm):
// Get all tasks in the realm
let tasks = realm.objects(QsTask.self)
// Retain notificationToken as long as you want to observe
let notificationToken = tasks.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
fatalError("\(error)")
}
}
// Delete all from the realm
try! realm.write {
realm.deleteAll()
}
// Add some tasks
let task = QsTask(partition: partitionValue, name: "Do laundry")
try! realm.write {
realm.add(task)
}
let anotherTask = QsTask(partition: partitionValue, name: "App design")
try! realm.write {
realm.add(anotherTask)
}
// You can also filter a collection
let tasksThatBeginWithA = tasks.filter("name beginsWith 'A'")
print("A list of all tasks that begin with A: \(tasksThatBeginWithA)")
// All modifications to a realm must happen in a write block.
let taskToUpdate = tasks[0]
try! realm.write {
taskToUpdate.status = "InProgress"
}
let tasksInProgress = tasks.filter("status = %@", "InProgress")
print("A list of all tasks in progress: \(tasksInProgress)")
// All modifications to a realm must happen in a write block.
let taskToDelete = tasks[0]
try! realm.write {
// Delete the QsTask.
realm.delete(taskToDelete)
}
print("A list of all tasks after deleting one: \(tasks)")
app.currentUser?.logOut { (error) in
// Logged out or error occurred
}
// Invalidate notification tokens when done observing
notificationToken.invalidate()
}
}
}

Running the above code should output something like the following:

Login as <RLMUser: 0x600002cc4ce0> succeeded!
... Sync: Connection[1]: Session[1]: client_reset_config = false, Realm exists = false, async open = false, client reset = false
... Sync: Connection[1]: Connected to endpoint '11.22.33.444:443' (from '192.168.1.2:51300')
... Sync: Connection[1]: Disconnected
... Sync: Connection[2]: Session[2]: client_reset_config = false, Realm exists = true, async open = false, client reset = false
Deleted indices: [0]
Inserted indices: [0]
Modified modifications: []
A list of all tasks that begin with A: Results<QsTask> <0x7ff1e642ae30> (
[0] QsTask {
_id = 5f8f65b040787581ba37e24e;
_partition = myPartition;
name = App design;
owner = (null);
status = ;
}
)
Deleted indices: []
Inserted indices: [0]
Modified modifications: []
A list of all tasks in progress: Results<QsTask> <0x7ff1e642b880> (
[0] QsTask {
_id = 5f8f65b040787581ba37e24e;
_partition = myPartition;
name = App design;
owner = (null);
status = InProgress;
}
)
Deleted indices: []
Inserted indices: []
Modified modifications: [0]
A list of all tasks after deleting one: Results<QsTask> <0x7ff1e54131b0> (
[0] QsTask {
_id = 5f8f65b040787581ba37e24d;
_partition = myPartition;
name = Do laundry;
owner = (null);
status = ;
}
)
... Sync: Connection[2]: Disconnected
Give Feedback