I think I might not have a complete full picture of how a synced Realm would work across devices.
Is data in realms initiated using the same logged-in logged-in user’s configuration stay in sync automatically when all devices have an internet connection? Do I need to set a global Realm observer to keep data on multiple devices up to date?
My setup
- The same app running in two Simulators
- Same Realm user logged in via API Key
When I initiate a synced Realm, The remote data on the cloud gets downloaded once the realm object is returned. The sync seems “stopped working” after the first opening. Adding new objects on either client would not upload the data to the server.
let realm = try? await Realm(configuration: config, downloadBeforeOpen: .once)
I noticed this because I have set up a syncSessionObserver
and the connectionState
was always either “.connecting” or “.disconnected”. I also set up a progress notification token and the callback never gets triggered.
syncSessionProgressToken = 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)%)")
}
syncSessionObserver = 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
}
}
However, after I added an observer for the return realm. I noticed the sync starts again. Now the change made on the other device would be detected, the connection status would be in “.connected”, and the realm log shows data been uploaded (e.g., Uploaded 10626B / 10626B (100.0%)
)
syncToken = realm?.observe { _, _ in
print(">>> DEBUG: [DCRealmProvider:getRealm] Sync realm data changed")
}
Full code snippet
public static func getRealm(for user:User?) async -> Realm? {
guard let user = user else { return userDataLocal.realm }
let userID = user.id
var config = user.configuration(partitionValue: userID)
config.objectTypes = REALM_CORE_OBJECT_TYPES
let realm = try? await Realm(configuration: config, downloadBeforeOpen: .once)
let syncSession = realm?.syncSession
syncToken = realm?.observe { _, _ in
print(">>> DEBUG: [RealmProvider:getRealm] Sync realm data changed")
}
syncSessionProgressToken = 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)%)")
}
syncSessionObserver = 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
}
}
return realm
}