Configurar e Abrir um Realm Sincronizado - Swift SDK
Nesta página
- Domínios sincronizados
- Realms sincronizados versus Realms não sincronizados
- Abrir um realm sincronizado
- Abra um domínio sincronizado na memória
- Abra um domínio sincronizado como um usuário de sincronização diferente
- Abra um Realm sincronizado com recursos de simultaneidade Swift
- Baixe as alterações antes de abrir
- Abrir um Realm Offline Sincronizado
Domínios sincronizados
Você pode configurar um domínio para sincronizar automaticamente os dados entre vários dispositivos, cada um com sua própria cópia local dos dados. Os domínios sincronizados usam uma configuração diferente dos domínios somente locais e exigem um backend do Atlas App Services para lidar com o processo de sincronização.
Os aplicativos podem sempre criar, modificar e excluir objetos de Realm sincronizados localmente, mesmo quando estiver offline. Sempre que uma conexão de rede está disponível, o Realm SDK abre uma conexão com um servidor de aplicação e sincroniza as alterações de e para outros clientes. O protocolo Atlas Device Sync e as transformações operacionais do lado do servidor garantem que todas as instâncias totalmente sincronizadas de um Realm vejam exatamente os mesmos dados, mesmo que algumas alterações tenham ocorrido offline e/ou tenham sido recebidas fora de ordem.
Dica
Saiba como configurar e usar a sincronização
Para obter mais informações sobre o Device Sync, incluindo instruções sobre como configurar a sincronização em um aplicativo do App Services, consulte Sincronizar dados.
Realms sincronizados versus Realms não sincronizados
Os realms sincronizados diferem dos realms locais não sincronizados de algumas maneiras:
Os realms sincronizados tentam sincronizar as alterações com os aplicativos de backend do App Services, enquanto os realms não sincronizados, não.
Os realms sincronizados podem ser acessados por usuários autenticados, enquanto os realms não sincronizados não têm nenhum conceito de usuários ou autenticação.
Com os domínios sincronizados, você pode especificar o comportamento de download para baixar atualizações antes de abrir um domínio. No entanto, exigir alterações no download antes de abrir o domínio exige que o usuário esteja online. Os domínios não sincronizados sempre podem ser usados offline.
Você pode copiar dados de um Realm não sincronizado para um Realm sincronizado e vice-versa, mas não é possível sincronizar um Realm não sincronizado . Para converter um Realm não sincronizado para um Realm sincronizado, você pode seguir o processo descrito em Migrar um aplicativo somente local para um aplicativo habilitado para sincronização.
Para obter mais informações sobre como configurar e abrir um domínio não sincronizado, consulte: Configurar e abrir um Realm - Swift SDK.
Abrir um realm sincronizado
Dica
Veja também:
Para obter informações sobre como abrir um realm de sincronização com base em partição, consulte Abrir um realm de sincronização com base em partição.
O fluxo típico para abrir um domínio sincronizado envolve:
Criando uma configuração de sincronização.
Abrindo o domínio sincronizado do usuário com a configuração.
Na autenticação, armazenamos credenciais de usuário em cache em um arquivo sync_metadata.realm
no dispositivo.
Ao abrir uma região sincronizada após a autenticação, você pode ignorar o fluxo de login e ir diretamente para a abertura da região sincronizada, usando a mesma configuração de sincronização já criada.
Com credenciais em cache, você pode:
Abra um realm sincronizado imediatamente com os dados que estão no dispositivo. Você pode usar esse método offline ou online.
Abra um domínio sincronizado após baixar as alterações de seu aplicativo. Isso exige que o usuário tenha uma conexão ativa com a Internet.
Ao utilizar a Flexible Sync, utilize o flexibleSyncConfiguration()
para abrir um domínio sincronizado.
Dica
Se a sua aplicação acessar Realm em um contexto do async/await
, marque o código com @MainActor
para evitar falhas relacionadas a threading.
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. 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
A Flexible Sync exige uma assinatura
Se o seu aplicativo usa sincronização de dispositivo padrão bidirecional, você não pode usar um domínio de sincronização flexível até adicionar pelo menos uma assinatura. Para saber como adicionar assinaturas, consulte: Adicionar uma assinatura.
Isso não se aplica ao ingestão de dados. Você não pode criar uma assinatura para um AsymmetricObject
.
Abra um domínio sincronizado na memória
Novidades na versão 10.46.0.
Você pode abrir um banco de dados sincronizado inteiramente na memória, que não cria um arquivo .realm
ou seus arquivos auxiliares associados. Em vez disso, o SDK armazena objetos na memória enquanto o realm está aberto e os descarta imediatamente quando todas as instâncias são fechadas.
Para abrir um domínio sincronizado na memória, defina a propriedade inMemoryIdentifier da configuração do domínio para um 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
Abra um domínio sincronizado como um usuário de sincronização diferente
Novidades na versão 10.23.0.
Se quiser abrir um domínio sincronizado como um usuário de sincronização diferente, você pode usar o método writeCopy (configuration:) para fazer uma cópia do domínio sincronizado para uso com a configuração de sincronização do novo usuário. O exemplo abaixo cria uma cópia do domínio sincronizado, com todos os seus dados existentes, que você pode usar com uma configuração de sincronização diferente.
Depois de copiar o realm para a configuração do novo usuário do Sync, você pode abrir a cópia como um realm sincronizado para esse usuário.
Observação
Somente sincronização do mesmo tipo
Esse método oferece suporte apenas à cópia de uma configuração de Partition-Based Sync para outro usuário de Partition-Based Sync ou uma configuração de Flexible Sync para outro usuário de Flexible Sync. Você não pode usar esse método para converter entre um Partition-Based Sync realm e um Flexible Sync realm ou vice-versa.
Dica
Se a sua aplicação acessar Realm em um contexto do async/await
, marque o código com @MainActor
para evitar falhas relacionadas a threading.
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. 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) }
Abra um Realm sincronizado com recursos de simultaneidade Swift
Você pode abrir um domínio sincronizado como um domínio isolado por ator usando recursos de simultaneidade do Swift:
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 obter mais informações sobre como trabalhar com domínios isolados por atores, consulte Use Realm with Actors - Swift SDK.
Baixe as alterações antes de abrir
Novidades na versão 10.15.0.
Quando você abre um domínio sincronizado com o Swift SDK, você pode passar o parâmetro downloadBeforeOpen
para especificar se deseja baixar o conjunto de alterações do seu aplicativo antes de abrir o domínio. Este parâmetro aceita um caso do enum OpenBehavior
:
never
: Abra imediatamente o domínio no dispositivo. Faça o download das alterações em segundo plano quando o usuário tiver internet, mas não bloqueie a abertura do domínio.always
: Verifique as alterações sempre que abrir o realm. Requer que o usuário tenha uma conexão ativa com a internet.once
: Baixe os dados antes de abrir um domínio pela primeira vez, mas abra-os sem baixar as alterações nas aberturas subsequentes. Isso permite que você preencha um domínio com dados iniciais, mas habilita a funcionalidade offline-first em aberturas subsequentes.
Dica
Se a sua aplicação acessar Realm em um contexto do async/await
, marque o código com @MainActor
para evitar falhas relacionadas a threading.
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
Abrir um Realm Offline Sincronizado
Quando seu aplicativo Realm autentica um usuário, armazena em cache as credenciais do usuário. Você pode verificar as credenciais de usuário existentes para ignorar o fluxo de login e acessar o usuário em cache. Use isto para abrir um realm offline.
Observação
O login inicial exige uma conexão de rede
Quando um usuário se inscreve em seu aplicativo ou faz login pela primeira vez com uma conta existente em um cliente, o cliente deve ter uma conexão de rede. A verificação de credenciais de usuário em cache permite que você abra um domínio offline, mas somente se o usuário já tiver feito login enquanto estiver online.
Você só poderá abrir um domínio sincronizado offline se seu aplicativo cliente always
não for configurada para baixar as alterações antes de abrir o domínio.
Dica
Se a sua aplicação acessar Realm em um contexto do async/await
, marque o código com @MainActor
para evitar falhas relacionadas a threading.
// 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)")