Docs Menu
Docs Home
/ /
Sincronizar datos

Configurar y abrir un dominio sincronizado - Swift SDK

Puedes configurar un dominio para que sincronice automáticamente datos entre varios dispositivos, cada uno con su propia copia local. Los dominios sincronizados utilizan una configuración diferente a la de los dominios locales y requieren un backend de Atlas App Services para gestionar el proceso de sincronización.

Las aplicaciones siempre pueden crear, modificar y eliminar objetos de dominio sincronizados localmente, incluso sin conexión. Siempre que haya una conexión de red disponible, el SDK de dominio abre una conexión con un servidor de aplicaciones y sincroniza los cambios con y desde otros clientes. El protocolo Atlas Device Sync y las transformaciones operativas del lado del servidor garantizan que todas las instancias totalmente sincronizadas de un reino vean exactamente los mismos datos, incluso si algunos cambios ocurrieron sin conexión y/o se recibieron fuera de orden.

Tip

Aprenda a configurar y utilizar la sincronización

Para obtener más información sobre la sincronización de dispositivos, incluidas instrucciones sobre cómo configurar la sincronización en una aplicación de App Services,consulta Sincronizar datos.

Los realms sincronizados difieren de los realms locales no sincronizados en algunos aspectos:

  • Los reinos sincronizados intentan sincronizar los cambios con su aplicación de servicios de aplicaciones de backend, mientras que los reinos no sincronizados no lo hacen.

  • Los usuarios autenticados pueden acceder a los reinos sincronizados, mientras que los reinos no sincronizados no tienen concepto de usuarios ni autenticación.

  • Con los dominios sincronizados, puedes especificar el comportamiento de descarga para descargar actualizaciones antes de abrir un dominio. Sin embargo, para solicitar que se descarguen los cambios antes de abrir el dominio, el usuario debe estar conectado. Los dominios no sincronizados siempre se pueden usar sin conexión.

Puedes copiar datos de un dominio no sincronizado a uno sincronizado y viceversa, pero no puedes sincronizar un dominio no sincronizado. Para convertir un dominio no sincronizado en uno sincronizado, sigue el proceso descrito en "Migrar una aplicación solo local a una aplicación sincronizada".

Para obtener más información sobre cómo configurar y abrir un reino no sincronizado, consulte: Configurar y abrirun reino - Swift SDK.

Tip

Para obtener información sobre cómo abrir un reino de sincronización basado en particiones, consulte Abrir un reino de sincronización basado en particiones.

El flujo típico para abrir un reino sincronizado implica:

  1. Autenticando al usuario.

  2. Creando una configuración de sincronización.

  3. Abriendo el reino sincronizado del usuario con la configuración.

Durante la autenticación, almacenamos en caché las credenciales del usuario en un sync_metadata.realm archivo en el dispositivo.

Cuando abres un reino sincronizado después de autenticarte, puedes omitir el flujo de inicio de sesión e ir directamente a abrir el reino sincronizado, utilizando la misma configuración de sincronización que ya creaste.

Con credenciales almacenadas en caché, puedes:

  • Abra inmediatamente un dominio sincronizado con los datos del dispositivo. Puede usar este método con o sin conexión.

  • Abra un reino sincronizado después de descargar los cambios desde su aplicación. Esto requiere que el usuario tenga una conexión a Internet activa.

Cuando utilice Sincronización flexible, utilice flexibleSyncConfiguration() para abrir un reino sincronizado.

Tip

Si su aplicación accede a Realm en un contexto async/await, marque el código con @MainActor para evitar fallas relacionadas con subprocesos.

let realm = try await openFlexibleSyncRealm()
// Opening a realm and accessing it must be done from the same thread.
// Marking this function as `@MainActor` avoids threading-related issues.
@MainActor
func openFlexibleSyncRealm() async throws -> Realm {
let app = App(id: APPID)
let credentials = emailPasswordCredentials(app: app)
let user = try await app.login(credentials: credentials)
var config = user.flexibleSyncConfiguration()
// Pass object types to the Flexible Sync configuration
// as a temporary workaround for not being able to add complete schema
// for a Flexible Sync app
config.objectTypes = [Task.self, Team.self]
let realm = try await Realm(configuration: config, downloadBeforeOpen: .always)
print("Successfully opened realm: \(realm)")
return realm
}

Importante

La sincronización flexible requiere una suscripción

Si tu aplicación utiliza Device Sync bidireccional estándar, no puedes usar un realm de Flexible Sync hasta que añadas al menos una suscripción. Para aprender a agregar suscripciones, consulta: Agregar una suscripción.

Esto no se aplica a la ingesta de datos. No se puede crear una suscripción para un.AsymmetricObject

Nuevo en la versión 10.46.0.

Puede abrir una base de datos sincronizada completamente en memoria, lo que no crea un .realm archivo ni sus archivos auxiliares asociados. En su lugar, el SDK almacena objetos en memoria mientras el dominio está abierto y los descarta inmediatamente al cerrar todas las instancias.

Para abrir un realm sincronizado en memoria, establece la propiedad inMemoryIdentifier de la configuración del realm como un identificador de string.

// Instantiate the app and get a user.
let app = App(id: APPID)
let user = try await app.login(credentials: Credentials.anonymous)
// Create a configuration.
var configuration = user.flexibleSyncConfiguration()
configuration.objectTypes = [Task.self, Team.self]
// Specify an in-memory identifier for the configuration.
configuration.inMemoryIdentifier = "YOUR-IDENTIFIER-STRING"
// Open a Realm with this configuration.
let realm = try await Realm(configuration: configuration)
print("Successfully opened realm: \(realm)")
// Add subscriptions and work with the realm

Nuevo en la versión 10.23.0.

Si desea abrir un dominio sincronizado con otro usuario de sincronización, puede usar el método writeCopy(configuration:) para crear una copia del dominio sincronizado y usarla con la configuración de sincronización del nuevo usuario. El siguiente ejemplo crea una copia del dominio sincronizado, con todos sus datos existentes, que puede usar con otra configuración de sincronización.

Después de copiar el reino para la configuración del nuevo usuario de sincronización, puede abrir la copia como un reino sincronizado para ese usuario.

Nota

Solo sincronización del mismo tipo

Este método solo permite copiar una configuración de sincronización basada en particiones para otro usuario de sincronización basada en particiones, o una configuración de sincronización flexible para otro usuario de sincronización flexible. No se puede usar este método para convertir entre un dominio de sincronización basada en particiones y uno de sincronización flexible, ni viceversa.

Tip

Si su aplicación accede a Realm en un contexto async/await, marque el código con @MainActor para evitar fallas relacionadas con subprocesos.

try await convertSyncedRealmForAnotherUser()
// Opening a realm and accessing it must be done from the same thread.
// Marking this function as `@MainActor` avoids threading-related issues.
@MainActor
func convertSyncedRealmForAnotherUser() async throws {
let app = App(id: YOUR_APP_SERVICES_APP_ID)
// Log in the user whose realm you want to use with another sync user
let frodoBaggins = try await app.login(credentials: Credentials.anonymous)
var frodoConfig = frodoBaggins.configuration(partitionValue: "Some Partition Value")
frodoConfig.objectTypes = [QsTask.self]
// Open the synced realm, and confirm it contains the data we want
// the other user to be able to access.
let frodoRealm = try await Realm(configuration: frodoConfig, downloadBeforeOpen: .always)
let frodoRealmTasks = frodoRealm.objects(QsTask.self)
let frodoSyncedTasks = frodoRealmTasks.where { $0.owner == "Frodo" }
XCTAssertEqual(frodoSyncedTasks.count, 3)
print("Successfully opened frodo's realm and it contains this many tasks: \(frodoSyncedTasks.count)")
// Log in as the user who will work with frodo's synced realm
let samwiseGamgee = try await app.login(credentials: Credentials.anonymous)
var samConfig = samwiseGamgee.configuration(partitionValue: "Some Partition Value")
samConfig.objectTypes = [QsTask.self]
// Specify an output directory for the copied realm
// We're using FileManager here for tested code examples.
guard let outputDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
// Append a file name to complete the path
let copiedRealmFilePath = outputDir.appendingPathComponent("copied.realm")
// Update the config file path to the path where you want to save the copied realm
samConfig.fileURL = copiedRealmFilePath
// Make a copy of frodo's realm that uses sam's config
try frodoRealm.writeCopy(configuration: samConfig)
// Open sam's realm, and see that it contains the same data as frodo's realm
let samRealm = try await Realm(configuration: samConfig)
let samRealmTasks = samRealm.objects(QsTask.self)
var samSyncedTasks = samRealmTasks.where { $0.owner == "Frodo" }
print("Successfully opened sam's realm and it contains this many tasks: \(samSyncedTasks.count)")
XCTAssertEqual(frodoSyncedTasks.count, samSyncedTasks.count)
// Add a task to sam's realm
let task = QsTask(value: ["name": "Keep an eye on that Gollum", "owner": "Sam"])
try! samRealm.write {
samRealm.add(task)
}
// See that the new task reflects in sam's realm, but not frodo's
samSyncedTasks = samRealmTasks.where { $0.owner == "Sam" }
XCTAssertEqual(samSyncedTasks.count, 1)
let samTasksInFrodoRealm = frodoRealmTasks.where { $0.owner == "Sam" }
XCTAssertEqual(samTasksInFrodoRealm.count, 0)
}

Puede abrir un reino sincronizado como un reino aislado del actor utilizando las funciones de concurrencia de Swift:

@MainActor
func mainThreadFunction() async throws {
// Initialize the app client and authenticate a user
let app = App(id: APPID)
let user = try await app.login(credentials: Credentials.anonymous)
// Configure the synced realm
var flexSyncConfig = user.flexibleSyncConfiguration(initialSubscriptions: { subs in
subs.append(QuerySubscription<Todo>(name: "all_todos"))})
flexSyncConfig.objectTypes = [Todo.self]
// Open and use the synced realm
let realm = try await Realm(configuration: flexSyncConfig, actor: MainActor.shared, downloadBeforeOpen: .always)
try await useTheSyncedRealm(realm: realm)
}

Para obtener más información sobre cómo trabajar con reinos aislados de actores, consulte Usar reino con actores - Swift SDK.

Nuevo en la versión 10.15.0.

Al abrir un dominio sincronizado con el SDK de Swift, puede pasar el parámetro downloadBeforeOpen para especificar si desea descargar el conjunto de cambios de su aplicación antes de abrir el dominio. Este parámetro acepta un caso de la enumeración OpenBehavior:

  • never: Abre el reino inmediatamente en el dispositivo. Descarga los cambios en segundo plano cuando el usuario tenga internet, pero no bloquea la apertura del reino.

  • always: Verifica los cambios cada vez que se abra el realm. Requiere que el usuario tenga una conexión a Internet activa.

  • onceDescargue los datos antes de abrir un reino por primera vez, pero ábralo sin descargar los cambios en las siguientes aperturas. Esto le permite completar un reino con los datos iniciales, pero habilita la función de inicio sin conexión en las siguientes aperturas.

Tip

Si su aplicación accede a Realm en un contexto async/await, marque el código con @MainActor para evitar fallas relacionadas con subprocesos.

func getRealmAfterDownloadingUpdates() async throws -> Realm {
let app = App(id: APPID)
let user = try await app.login(credentials: Credentials.anonymous)
var configuration = user.flexibleSyncConfiguration()
configuration.objectTypes = [FlexibleSync_Task.self, FlexibleSync_Team.self]
let realm = try await Realm(configuration: configuration, downloadBeforeOpen: .always)
print("Successfully opened realm after downloading: \(realm)")
return realm
}
let realm = try await getRealmAfterDownloadingUpdates()
print("The open realm is: \(realm)")
// Add subscription and work with the realm

Cuando tu aplicación Realm autentica a un usuario, almacena en caché las credenciales del usuario. Puedes comprobar si existen credenciales de usuario para omitir el flujo de inicio de sesión y acceder al usuario almacenado en caché. Usa esto para abrir un realm sin conexión.

Nota

El inicio de sesión inicial requiere una conexión de red

Cuando un usuario se registra en tu aplicación o inicia sesión por primera vez con una cuenta existente en un cliente, este debe tener conexión de red. Comprobar las credenciales de usuario en caché permite abrir un reino sin conexión, pero solo si el usuario ha iniciado sesión previamente con conexión.

Solo puedes abrir un reino sincronizado sin conexión si no necesitas que tu aplicación cliente always descargue los cambios antes de abrir el reino.

Tip

Si su aplicación accede a Realm en un contexto async/await, marque el código con @MainActor para evitar fallas relacionadas con subprocesos.

// Log the user into the backend app.
// The first time you login, the user must have a network connection.
func getUser() async throws -> User {
// Check for an existing user.
// If the user is offline but credentials are
// cached, this returns the existing user.
if let user = app.currentUser {
return user
} else {
// If the device has no cached user
// credentials, log them in.
let app = App(id: YOUR_APP_SERVICES_APP_ID)
let loggedInUser = try await app.login(credentials: Credentials.anonymous)
return loggedInUser
}
}
let user = try await getUser()
var configuration = user.configuration(partitionValue: "Some Partition Value")
// Open a Realm with this configuration.
// If you do not require the app to download updates
// before opening the realm, the realm just opens, even if
// offline.
let realm = try await Realm(configuration: configuration)
print("Successfully opened realm: \(realm)")

Volver

Agregar sincronización a una aplicación

En esta página