Navigation

Sync Changes Between Devices - iOS SDK

Important

Realm Sync does not currently support watchOS.

To open a synced realm, pass the logged-in user's Configuration object with the desired partition value to Realm.asyncOpen(configuration:):

asyncOpen downloads the entire remote realm before opening a local version.

let app = App(id: YOUR_REALM_APP_ID)
// Log in...
let user = app.currentUser
let partitionValue = "some partition value"
var configuration = user!.configuration(partitionValue: partitionValue)
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):
print("Successfully opened realm: \(realm)")
// Use realm
}
}

You can also open the realm immediately with the Realm() initializers. This works if the device is offline, but may lead to temporary data inconsistencies while your app downloads the remote data.

let realm = try! Realm(configuration: configuration)
print("Opened realm: \(realm)")

If you want your app to update data in the background (while the app is minimized), iOS requires you to implement Background App Refresh. Enabling Background App Refresh minimizes the time it takes for the user to see the most recent data; without Background App Refresh, MongoDB Realm updates the data when the user launches the app, potentially resulting in noticeable lag.

To use the realm while the device is locked, you must adjust the file protection settings. See Use Realm When the Device Is Locked.

You can suspend or resume a sync session using the SyncSession instance of a synced realm.

let syncSession = syncedRealm.syncSession!
// Suspend synchronization
syncSession.suspend()
// Later, resume synchronization
syncSession.resume()

You can add a progress notification using the synced realm's SyncSession instance's addProgressNotification(for:mode:block:) method.

This method returns a token that you should retain until you wish to stop observing upload or download progress. Note that if you keep the token in a local variable, observation will stop when the local variable goes out of scope.

let syncSession = syncedRealm.syncSession!
let token = syncSession.addProgressNotification(
for: .upload, mode: .forCurrentlyOutstandingWork) { (progress) in
let transferredBytes = progress.transferredBytes
let transferrableBytes = progress.transferrableBytes
let transferPercent = progress.fractionTransferred * 100
print("Uploaded \(transferredBytes)B / \(transferrableBytes)B (\(transferPercent)%)")
}
// Upload something
try! syncedRealm.write {
syncedRealm.add(Task())
}
Tip

MongoDB Realm's offline-first design means that you generally don't need to check the current network connection state. That said, the connectionState property is available if your app calls for some indication of connection state.

To check the connection state, you can read the synced realm's SyncSession instance's connectionState property directly.

This property is KVO-compliant, so you can observe changes using KVO or even Combine.

// Observe connectionState for changes using KVO
let observer = syncSession.observe(\.connectionState, options: [.initial]) { (syncSession, change) in
switch syncSession.connectionState {
case .connecting:
print("Connecting...")
case .connected:
print("Connected")
case .disconnected:
print("Disconnected")
default:
break
}
}
// Observe using Combine
let cancellable = syncSession.publisher(for: \.connectionState)
.sink { connectionState in
switch connectionState {
case .connecting:
print("Connecting...")
case .connected:
print("Connected")
case .disconnected:
print("Disconnected")
default:
break
}
}

While developing an application that uses Realm Sync, you should set an error handler. This error handler will detect and respond to any failed sync-related API calls.

Set an error handler on the SyncManager singleton. Set an error handler on the SyncManager singleton. When an error occurs, the iOS SDK calls the error handler with the error object and the SyncSession that the error occurred on.

Note

Realm's SyncError conforms to Swift's Error protocol

let app = App(id: YOUR_REALM_APP_ID)
app.syncManager.errorHandler = { error, session in
// handle error
}

In some cases, you may want to completely delete a realm file from disk.

Realm avoids copying data into memory except when absolutely required. As a result, all objects managed by a realm have references to the file on disk. Before you can safely delete the file, you must ensure the deallocation of these objects:

  • All objects read from or added to the realm
  • All List and Results objects
  • All ThreadSafeReference objects
  • The realm itself

In practice, there are two safe times to delete the realm file:

  1. On application startup before ever opening the realm.
  2. After only having opened the realm within an explicit autorelease pool, which ensures deallocation of all of objects within it.

You can delete the .realm, .note and .management files for a given configuration with the Realm.deleteFiles(for:) class method.

autoreleasepool {
// all Realm usage here -- explicitly guarantee
// that all realm objects are deallocated
// before deleting the files
}
do {
let app = App(id: YOUR_REALM_APP_ID)
var configuration = app.currentUser!.configuration(partitionValue: "some partition value")
_ = try Realm.deleteFiles(for: configuration)
} catch {
// handle error
}
Tip

To see how to recover unsynced local changes in a client reset, check out this example on GitHub.

You can set the Realm Sync client log level on the SyncManager instance on your App.

// Access your app
let app = App(id: YOUR_REALM_APP_ID)
// Access the sync manager for the app
let syncManager = app.syncManager
// Set the logger to provide debug logs
syncManager.logLevel = .debug
Give Feedback