Docs Menu
Docs Home
/ /
Sincronizar datos

Administrar sesiones de sincronización - Swift SDK

Al abrir un reino sincronizado se inicia un Sesión de sincronización para ese dominio. El SDK de Swift para dominios proporciona métodos para pausar y reanudar manualmente una sesión de sincronización.

Nuevo en la versión 10.41.0.

En la versión 10.41.0 y posteriores del SDK de Realm Swift, App Services comparte una única conexión al servidor de forma predeterminada para todos los reinos sincronizados abiertos. Esto supone un cambio respecto a versiones anteriores, donde al abrir más de un reino sincronizado se abrían conexiones adicionales al servidor. La conexión al servidor es independiente de... SyncSession, y se basa en el usuario de App Services.

Puede cambiar este comportamiento desde la configuración del cliente de la aplicación.

Tip

El diseño de Realm, que prioriza el uso sin conexión, implica que, por lo general, no es necesario verificar el estado actual de la conexión de red. Dicho esto, la connectionState propiedad está disponible si la aplicación solicita alguna indicación del estado de la conexión.

Para comprobar el estado de la conexión, puede leer directamente la propiedad connectionState de la instancia RLMSyncSession del reino sincronizado.

Esta propiedad cumple con la normativa KVOPara que puedas observar los cambios usando KVO. El siguiente ejemplo muestra cómo implementar una clase observadora:

@interface MySyncSessionObserver: NSObject
@end
@implementation MySyncSessionObserver
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (![object isKindOfClass:RLMSyncSession.class]) {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
return;
}
if (![keyPath isEqualToString:@"connectionState"]) {
// Not interested in observing this keypath
return;
}
RLMSyncSession *syncSession = (RLMSyncSession *)object;
RLMSyncConnectionState connectionState = [syncSession connectionState];
switch (connectionState) {
case RLMSyncConnectionStateConnecting:
NSLog(@"Connecting...");
break;
case RLMSyncConnectionStateConnected:
NSLog(@"Connected");
break;
case RLMSyncConnectionStateDisconnected:
NSLog(@"Disconnected");
break;
}
}
@end

A continuación, puede adjuntar una instancia de observador al objeto RLMSyncSession. Asegúrese de eliminar el observador al finalizar.

// Observe connectionState for changes using KVO
MySyncSessionObserver *observer = [[MySyncSessionObserver alloc] init];
[syncSession addObserver:observer
forKeyPath:@"connectionState"
options:NSKeyValueObservingOptionInitial
context:nil];
// Later, when done...
[syncSession removeObserver:observer
forKeyPath:@"connectionState"
context:nil];

Para comprobar el estado de la conexión, puede leer directamente la propiedad connectionState de la instancia SyncSession del reino sincronizado.

Esta propiedad es compatible con KVO, por lo que puedes observar cambios usando KVO o incluso 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
}
}

Puedes suspender y reanudar la sesión de sincronización en el reino. Pausar una sesión de sincronización solo suspende la sesión de sincronización de ese reino. Si tienes más de un reino abierto, la suspensión no afecta las sesiones de sincronización de los demás reinos.

Puede suspender o reanudar una sesión de sincronización utilizando la instancia RLMSyncSession de un reino sincronizado.

RLMRealm *syncedRealm = [RLMRealm realmWithConfiguration:configuration error:nil];
RLMSyncSession *syncSession = [syncedRealm syncSession];
// Suspend synchronization
[syncSession suspend];
// Later, resume synchronization
[syncSession resume];

Puede suspender o reanudar una sesión de sincronización utilizando la instancia SyncSession de un reino sincronizado.

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

En la mayoría de las aplicaciones, no es necesario pausar y reanudar manualmente una sesión de sincronización. Sin embargo, existen algunas circunstancias en las que podría ser conveniente pausar o suspender una sesión de sincronización:

  • Solo desea sincronizar después de que el usuario realice una acción específica

  • Solo desea sincronizar durante un momento determinado del día.

  • No debes intentar sincronizar cuando hay una mala conectividad de red

  • Quiere forzar explícitamente una sesión de sincronización para conectarse

En el caso de una mala conectividad de red, intentar continuamente establecer una conexión de red puede agotar la batería del dispositivo del usuario.

El caso de forzar explícitamente la conexión de una sesión de sincronización suele estar relacionado con estar desconectado durante un tiempo. El cliente de sincronización intenta conectarse y, al fallar, entra en una fase de desconexión exponencial. Tras un tiempo prolongado desconectado, es posible que el cliente no se vuelva a conectar inmediatamente. Pausar y reanudar la sesión de sincronización fuerza explícitamente la conexión.

Cuando pause una sesión de sincronización, tenga en cuenta lo siguiente:

  • Si el cliente puede estar fuera de línea por un tiempo mayor al máximo permitido, no podrá reanudar la sincronización y deberá reiniciarlo.

  • Pausar una sesión de sincronización la pausa en ambos sentidos. Los cambios que realiza la aplicación en el dispositivo no se sincronizan con el backend, y los cambios en los datos del backend o de otros dispositivos no se sincronizan con el dispositivo. No es posible pausar solo las cargas ni las descargas.

  • No pause una sesión de sincronización si desea que un cliente deje de sincronizarse permanentemente con el backend. Para ello, copie el contenido del dominio sincronizado en uno no sincronizado y utilice este último en el cliente.

No pause la sincronización para detenerla por períodos indefinidos o intervalos de tiempo de meses o años. Esta función no está diseñada ni probada para estos casos de uso. Podría experimentar diversos problemas al usarla de esta manera.

Nuevo en la versión 10.45.0.

Para esperar a que todos los cambios se carguen o descarguen desde su reino sincronizado, llame a realm.syncSession?.wait(for: ).

Este método toma un argumento ProgressDirection para especificar si se debe realizar un seguimiento del progreso de carga o descarga.

Puedes usar estos métodos con la sintaxis async/await de Swift o con la sintaxis de devolución de llamada. La versión de devolución de llamada, realm.syncSession?.wait(for:queue:block:), puede usar una cola para enviar la devolución de llamada y un bloque para invocar al finalizar la espera.

// Wait to download all pending changes from Atlas
try await realm.syncSession?.wait(for: .download)
// Add data locally
try realm.write {
realm.create(Task.self, value: [
"taskName": "Review proposal",
"assignee": "Emma",
"completed": false,
"progressMinutes": 0,
"dueDate": date
])
}
// Wait for local changes to be uploaded to Atlas
try await realm.syncSession?.wait(for: .upload)
// Wait to download all pending changes from Atlas
realm.syncSession?.wait(for: .download, block: { _ in
// You can provide a block to execute
// after waiting for download to complete
})
// Add data locally
do {
try realm.write {
realm.create(Task.self, value: [
"taskName": "Review proposal",
"assignee": "Emma",
"completed": false,
"progressMinutes": 0,
"dueDate": date
])
}
} catch {
print("There was an error writing to realm: \(error.localizedDescription)")
}
// Wait for local changes to be uploaded to Atlas
realm.syncSession?.wait(for: .upload, block: { _ in
// You can provide a block to execute after
// waiting for upload to complete
})

Cambiado en la 10.50.0 versión: transferredBytes y quedaron transferrableBytes obsoletos en favor de progressEstimate

Puede comprobar el progreso de carga y descarga registrando un token que proporciona un progressEstimate para una dirección de carga o descarga y un alcance de trabajo determinados. Puede establecer un ProgressMode para determinar el alcance de trabajo: observar indefinidamente o cancelar el registro del bloque una vez completado el elemento de trabajo actual.

El valor progressEstimate proporcionado por el token es un valor doble cuyo valor oscila entre 0.0 y 1.0. En 1.0, la carga o descarga se completa. Puede usar este progressEstimate para mostrar un indicador de progreso o un porcentaje estimado de transferencia de datos.

Cambiado en la 10.50.0 versión: addProgressNotificationForDirection obsoleto en favor de addSyncProgressNotificationForDirection

Puede añadir una notificación de progreso usando la instancia RLMSyncSession del realm sincronizado con el método [--addSyncProgressNotificationForDirection:moda:block:].

Este método devuelve un token que debe conservar hasta que desee dejar de observar el progreso de carga o descarga. Tenga en cuenta que si conserva el token en una variable local, la observación se detendrá cuando la variable local quede fuera de alcance.

RLMSyncSession *syncSession = [syncedRealm syncSession];
RLMProgressNotificationToken *token = [syncSession
addSyncProgressNotificationForDirection:RLMSyncProgressDirectionUpload
mode:RLMSyncProgressModeForCurrentlyOutstandingWork
block:^(RLMSyncProgress syncProgress) {
NSLog(@"Uploaded %fB", (double)syncProgress.progressEstimate);
}];
// Upload something
[syncedRealm transactionWithBlock:^{
[syncedRealm addObject:[[Task alloc] init]];
}];

Puede agregar una notificación de progreso utilizando el método addProgressNotification(for:mode:block:) de la instancia SyncSession del reino sincronizado.

Este método devuelve un token que debe conservar hasta que desee dejar de observar el progreso de carga o descarga. Tenga en cuenta que si conserva el token en una variable local, la observación se detendrá cuando la variable local quede fuera de alcance.

let syncSession = realm.syncSession!
let token = syncSession.addProgressNotification(
for: .upload, mode: .forCurrentlyOutstandingWork) { (progress) in
let progressEstimate = progress.progressEstimate
let transferPercent = progressEstimate * 100
print("Uploaded (\(transferPercent)%)")
}

Nuevo en la versión 10.44.0.

Realm detecta automáticamente cuando un dispositivo recupera la conectividad tras estar desconectado e intenta reconectarse mediante una estrategia de desconexión gradual. Por ejemplo, en las plataformas Apple, Realm detecta las notificaciones de cambio de red y activa automáticamente una reconexión inmediatamente después de recibirlas.

En la versión 10.44.0 y posteriores del SDK de Swift, puedes elegir activar manualmente un intento de reconexión con SyncSession.reconnect() en vez de esperar la duración de la retroceso incremental. Esto es útil si tienes una comprensión más precisa de las condiciones de la red y no deseas depender de la detección automática de reconexión de Realm.

let syncSession = realm.syncSession!
// Work with the realm. When you need to force the sync session to reconnect...
syncSession.reconnect()

Al llamar a este método, el SDK fuerza a todas las sesiones de sincronización a intentar reconectarse inmediatamente. Esto restablece los temporizadores utilizados para la interrupción incremental.

Llamar a este método no garantiza que el dispositivo pueda reconectarse. Si el SDK recibe un error fatal, o si el dispositivo ya está conectado o intenta conectarse, llamar a este método no tiene ningún efecto.

Importante

No se puede reconectar dentro del tiempo de espera de lectura del socket

Realm tiene un tiempo de espera interno por defecto para la lectura de socket de 2 minutos; Realm dará tiempo de espera si una operación de lectura no recibe ningún dato dentro de una ventana de 2 minutos. Si llamas a SyncSession.reconnect() dentro de esa ventana, el SDK de Swift no intentará reconectar.

Volver

Sincronizar datos en segundo plano

En esta página