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.
Comportamento da conexã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.
Verifique a conexão de rede
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 } }
Suspender ou retomar uma sessão de sincronização
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()
Quando pausar uma sessão de sincronização
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.
Aguarde as alterações para fazer upload ou download
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 })
Verificar o progresso do upload e download de uma sessão de sincronização
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)%)") }
Reconectar manualmente todas as sessões de sincronização
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.