Does sync Realm stay in-sync across devices automatically while the app is running with Internet connection?

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
}