Menu Docs
Página inicial do Docs
/ /
Atlas Device SDKs
/ /

Managed sessões de sincronização - Swift SDK

Nesta página

  • Comportamento da conexão de sincronização
  • Verifique a conexão de rede
  • Suspender ou retomar uma sessão de sincronização
  • Quando pausar uma sessão de sincronização
  • Aguarde as alterações para fazer upload ou download
  • Verificar o progresso do upload e download de uma sessão de sincronização
  • Reconectar manualmente todas as sessões de sincronização

A abertura de um Realm sincronizado inicia uma SyncSession para esse Realm. O Realm Swift SDK fornece métodos para pausar e retomar manualmente uma sessão de sincronização.

Novo na versão 10.41.0.

No Realm Swift SDK versão 10.41.0 e posterior, o App Services tem como padrão compartilhar uma única conexão com o servidor para todos os domínios sincronizados abertos. Esta é uma mudança em relação às versões anteriores, em que a abertura de mais de um Realm sincronizado abria conexões adicionais com o servidor. A conexão com o servidor é independente do SyncSession e é baseada no usuário do App Services.

Você pode alterar esse comportamento na configuração do cliente do aplicativo.

Dica

O design offline do Realm significa que geralmente você não precisa verificar o estado atual da conexão de rede. Dito isto, a propriedade connectionState está disponível se a sua aplicação chamar alguma indicação do estado da conexão.

Para verificar o estado da conexão, você pode ler a propriedade connectionState da instância RLMSyncSession do domínio sincronizado diretamente.

Esta propriedade é compatível com KVO , para que você possa observar alterações usando KVO. O exemplo a seguir demonstra como implementar uma classe de observador:

@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

Em seguida, você pode anexar uma instância de observador ao objeto RLMSyncSession. Certifique-se de remover o observador quando terminar.

// 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 verificar o estado da conexão, você pode ler a propriedade connectionState da instância SyncSession do domínio sincronizado diretamente.

Esta propriedade está em conformidade com KVO , para que você possa observar alterações usando KVO ou até mesmo 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
}
}

Você pode suspender e retomar a sessão de sincronização no Realm. Pausar uma sessão de sincronização suspende apenas a sessão de sincronização desse realm. Se você tiver mais de um Realm aberto, a suspensão não afetará a sessão de sincronização de outros Realms.

Você pode suspender ou retomar uma sessão de sincronização usando a instância RLMSyncSession de um Realm sincronizado.

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

Você pode suspender ou retomar uma sessão de sincronização usando a instância SyncSession de um domínio sincronizado.

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

Para a maioria dos aplicativos, não é necessário pausar e retomar manualmente uma sessão de sincronização. No entanto, existem algumas circunstâncias em que você pode querer pausar ou suspenso uma sessão de sincronização:

  • Você só quer sincronizar depois que o usuário executar uma ação específica

  • Você só deseja sincronizar durante um determinado horário do dia

  • Você não quer tentar sincronizar quando a conectividade de rede estiver ruim

  • Você deseja forçar explicitamente uma sessão de sincronização para se conectar

No caso de uma conectividade de rede ruim, tentar continuamente estabelecer uma conexão de rede pode esgotar a bateria do dispositivo do usuário.

O caso de forçar explicitamente uma sessão de sincronização para se conectar é mais comumente relacionado a estar offline por algum tempo. O cliente de sincronização tenta se conectar e, em caso de falha, entra em backoff exponencial. After being offline for a long time, the client may not immediately reconnect. Pausar e retomar a sessão de sincronização força explicitamente a conexão.

Ao pausar uma sessão de sincronização, lembre-se do seguinte:

  • Se o cliente ficar offline por mais tempo do que o tempo máximo offline do cliente , o cliente não conseguirá retomar a sincronização e deverá fazer um reinício do cliente.

  • Pausar uma sessão de sincronização a pausa em ambas as direções. As alterações feitas pelo seu aplicativo no dispositivo não são sincronizadas com o backend, e as alterações nos dados no backend ou em outros dispositivos não são sincronizadas com o dispositivo. Não há como pausar apenas uploads ou pausar apenas downloads.

  • Não pause uma sessão de sincronização se quiser que um cliente pare permanentemente de sincronizar com o backend. Para parar permanentemente a sincronização, copie o conteúdo do Realm sincronizado em um Realm não sincronizado e use o Realm não sincronizado no cliente.

Não pause a sincronização para parar a sincronização por períodos indefinidos ou intervalos de tempo em meses e anos. A funcionalidade não foi projetada ou testada para esses casos de uso. Você pode encontrar uma série de problemas ao usá-lo dessa forma.

Novidade na versão 10.45.0.

Para aguardar o upload ou download de todas as alterações do seu Realm sincronizado , chame Realm.syncSession?.wait(for: ).

Este método utiliza um argumento ProgressDirection para especificar se deseja acompanhar o progresso do upload ou download.

Você pode usar esses métodos com a sintaxe async/await do Swift ou com a sintaxe de chamada de resposta de chamada. A versão de chamada de resposta de resposta, Realm.syncSession?.wait(for:queue:block:), pode pegar uma fila para despachar a chamada de resposta de resposta e um bloco para invocar quando a espera for concluída.

// 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
})

Alterado na versão 10.50.0: transferredBytes e transferrableBytes preteridos a favor de progressEstimate

Você pode conferir o progresso do upload e download registrando um token que fornece um progressEstimate para uma determinada direção de upload ou download e escopo de trabalho. Você pode definir um ProgressMode para determinar o escopo do trabalho: observar indefinidamente ou cancelar o registro do bloqueio após a conclusão do item de trabalho atual.

O valor progressEstimate fornecido pelo token é um valor double cujo valor varia de 0.0 a 1.0. Em 1.0, o upload ou download está concluído. Você pode usar esse progressEstimate para exibir um indicador de progresso ou uma porcentagem estimada de transferência de dados .

Alterado na versão 10.50.0: addProgressNotificationForDirection preterido em favor de addSyncProgressNotificationForDirection

Você pode adicionar uma notificação de progresso usando o método [--addSyncProgressNotificationForDirection:mode:block:] da instância RLMSyncSession do domínio sincronizado.

Esse método retorna um token que você deve reter até que queira parar de observar o progresso do upload ou download. Observe que, se você manter o token em uma variável local, a observação será interrompida quando a variável local sair do escopo.

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]];
}];

Você pode adicionar uma notificação de progresso usando o método addProgressNotification(for:mode:block:) da instância SyncSession do domínio sincronizado.

Esse método retorna um token que você deve reter até que queira parar de observar o progresso do upload ou download. Observe que, se você manter o token em uma variável local, a observação será interrompida quando a variável local sair do escopo.

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)%)")
}

Novidade na versão 10.44.0.

O Realm detecta automaticamente quando um dispositivo recupera a conectividade depois de estar offline e tenta se reconectar usando uma estratégia de backoff incremental. Por exemplo, em plataformas Apple, o Realm escuta notificações de alteração de rede e Atlas Triggers automaticamente uma reconexão imediatamente após o recebimento de uma.

No Swift SDK versão 10.44.0 e posterior, você pode optar por trigger manualmente uma tentativa de reconexão com SyncSession.reconnect() em vez de esperar pela duração do backoff incremental. Isso é útil se você tiver uma compreensão mais precisa das condições da rede e não quiser confiar na detecção automática de reconexão do Realm.

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

Quando você chama esse método, o SDK força todas as sessões de sincronização a tentar se reconectar imediatamente. Isso redefine todos os temporizadores usados para backoff incremental.

Chamar esse método não garante que o dispositivo possa se reconectar. Se o SDK receber um erro fatal ou se o dispositivo já estiver conectado ou tentando se conectar, chamar esse método não terá efeito.

Importante

Não é possível reconectar dentro da duração do tempo limite de leitura do soquete

O Realm tem um tempo limite de leitura de soquete padrão interno de 2 minutos, onde o Realm atingirá o tempo limite se uma operação de leitura não receber nenhum dado dentro de uma janela de 2 minutos. Se você chamar SyncSession.reconnect() dentro dessa janela, o Swift SDK não tentará se reconectar.

Voltar

Sincronizar dados em segundo plano