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

Sincronize dados em segundo plano com o SwiftUI - Swift SDK

Nesta página

  • Visão geral
  • Habilite modos de fundo para seu aplicativo
  • Adicionar capacidade de modos de fundo
  • Selecionar Modos de Fundo
  • Atualize o Info.plist
  • Agendar uma tarefa em segundo plano
  • Criar a tarefa de background
  • Teste sua tarefa de Background
  • Configurar um dispositivo para executar seu aplicativo
  • Definir um ponto de interrupção
  • Execute o aplicativo
  • Adicionar ou Alterar Dados no Atlas
  • Invocar a tarefa de plano de fundo no LLDB
  • Ativar o modo avião no dispositivo
  • Abra o aplicativo

Você pode usar um SwiftUI BackgroundTask para atualizar um Realm sincronizado quando seu aplicativo estiver em segundo plano. Este exemplo demonstra como configurar e executar a sincronização em segundo plano em um aplicativo para iOS.

Você pode acompanhar o exemplo nesta página usando o aplicativo SwiftUI Device Sync Template. Para obter sua própria cópia do SwiftUI Device Sync Template, confira o tutorialDevice Sync SwiftUI e Go as seções Prerequisites e Start with the Template.

Para ativar tarefas em segundo plano para seu aplicativo:

1

Selecione seu destino do aplicativo, vá até a aba Signing & Capabilities e clique em + Capability para adicionar o recurso.

Captura de tela do Xcode com o destino selecionado do aplicativo, a guia Signing & Capabilities (Assinatura e Recursos) é aberta e a seta apontando para adicionar recursos.
clique para ampliar

Procure por "fundo" e selecione Background Modes.

2

Agora você deve ver uma seção Background Modes em sua aba Signing & Capabilities. Expanda esta seção e clique nas caixas de seleção para habilitar Background fetch e Background processing.

3

Acesse Info.plist do seu projeto e adicione uma nova linha para Permitted background task scheduler identifiers. Se você estiver visualizando chaves e valores brutos, a chave será BGTaskSchedulerPermittedIdentifiers. Este campo é uma matriz. Adicione um novo item para seu identificador de tarefa em segundo plano. Defina o valor do novo item para a string que pretende usar como identificador para sua tarefa de plano de fundo. Por exemplo: refreshTodoRealm.

Depois de habilitar processos em segundo plano para seu aplicativo, você pode começar a adicionar o código ao aplicativo para agendar e executar uma tarefa em segundo plano. Primeiro, importe BackgroundTasks nos arquivos onde você irá escrever este código:

import SwiftUI
import RealmSwift
import BackgroundTasks

Agora você pode adicionar uma tarefa de plano de fundo agendada. Se você estiver acompanhando por meio do aplicativo Template, você pode atualizar sua visualização @main:

@main
struct realmSwiftUIApp: SwiftUI.App {
@Environment(\.scenePhase) private var phase
var body: some Scene {
WindowGroup {
ContentView(app: realmApp)
}
.onChange(of: phase) { newPhase in
switch newPhase {
case .background: scheduleAppRefresh()
default: break
}
}
}

Você pode adicionar uma variável de ambiente para armazenar uma alteração no scenePhase: @Environment(\.scenePhase) private var phase.

Em seguida, você pode adicionar o bloco .onChange(of: phase) que chama a função scheduleAppRefresh() quando o aplicativo fica em segundo plano.

Crie a função scheduleAppRefresh():

func scheduleAppRefresh() {
let backgroundTask = BGAppRefreshTaskRequest(identifier: "refreshTodoRealm")
backgroundTask.earliestBeginDate = .now.addingTimeInterval(10)
try? BGTaskScheduler.shared.submit(backgroundTask)
}

Isso agenda o trabalho para executar a tarefa em segundo plano cujo identificador você adicionou ao Info.plist acima quando ativou os modos em segundo plano. Neste exemplo, o identificador refreshTodoRealm refere-se a esta tarefa.

Agora que você agendou a tarefa em segundo plano, precisa criar a tarefa em segundo plano que será executada para atualizar o domínio sincronizado.

Se você estiver acompanhando o aplicativo Template, você pode adicionar esse backgroundTask à sua visualização @main, depois do .onChange(of: phase):

.onChange(of: phase) { newPhase in
switch newPhase {
case .background: scheduleAppRefresh()
default: break
}
}
.backgroundTask(.appRefresh("refreshTodoRealm")) {
guard let user = realmApp.currentUser else {
return
}
let config = user.flexibleSyncConfiguration(initialSubscriptions: { subs in
if let foundSubscription = subs.first(named: "user_tasks") {
foundSubscription.updateQuery(toType: Item.self, where: {
$0.owner_id == user.id
})
} else {
subs.append(QuerySubscription<Item>(name: "user_tasks") {
$0.owner_id == user.id
})
}
}, rerunOnOpen: true)
await refreshSyncedRealm(config: config)
}

Essa tarefa de background, primeiro confira se o aplicativo tem um usuário conectado. Em caso afirmativo, é definida um .flexibleSyncConfiguration com uma inscrição que o aplicativo pode usar para sincronizar o realm.

Esta é a mesma configuração usada no ContentView do aplicativo Template. No entanto, para usá-lo aqui, você precisa acessá-lo mais acima na hierarquia de visualização. Você pode refatorar isso para uma função que pode chamar de qualquer visualização que usa um usuário como parâmetro e retorna um Realm.Configuration.

Finalmente, essa tarefa espera o resultado de uma função que realmente sincroniza o domínio. Adicionar esta função:

func refreshSyncedRealm(config: Realm.Configuration) async {
do {
try await Realm(configuration: config, downloadBeforeOpen: .always)
} catch {
print("Error opening the Synced realm: \(error.localizedDescription)")
}
}

Ao abrir esse reino sincronizado e usar o parâmetro downloadBeforeOpen para especificar que deseja baixar as atualizações, você carrega os dados novos no domínio em segundo plano. Então, quando seu aplicativo abrir novamente, ele já tem os dados atualizados no dispositivo.

Importante

Não tente escrever no domínio diretamente nesta tarefa em segundo plano. Você pode encontrar problemas relacionados ao thread devido à arquitetura confinada de threads do Realm.

Ao agendar uma tarefa em segundo plano, você está definindo a primeira vez que o sistema pode executar a tarefa. No entanto, o sistema operacional leva em consideração muitas outras considerações que podem atrasar a execução da tarefa em segundo plano muito depois da earliestBeginDate agendada. Em vez de esperar que um dispositivo execute a tarefa em segundo plano para verificar se ela faz o que você pretende, você pode definir um ponto de interrupção e usar o LLDB para invocar a tarefa.

1

Para testar se sua tarefa em segundo plano é atualizar o domínio sincronizado em segundo plano, você precisará de um dispositivo físico com, no mínimo, iOS 16. Seu dispositivo deve estar configurado para ser executado no Modo Desenvolvedor. Se você receber uma notificação Untrusted Developer, Go Settings, General e VPN & Device Management. Aqui, você pode verificar que deseja executar o aplicativo que está desenvolvendo.

Depois de executar seu aplicativo com sucesso em seu dispositivo, você poderá testar a tarefa em segundo plano.

2

Comece definindo um ponto de interrupção na função scheduleAppRefresh() . Defina o ponto de interrupção após a linha para onde você envia a tarefa para BGTaskScheduler. Para este exemplo, você pode adicionar uma linha print e definir o ponto de quebra na linha de impressão:

func scheduleAppRefresh() {
let backgroundTask = BGAppRefreshTaskRequest(identifier: "refreshTodoRealm")
backgroundTask.earliestBeginDate = .now.addingTimeInterval(10)
try? BGTaskScheduler.shared.submit(backgroundTask)
print("Successfully scheduled a background task") // Set a breakpoint here
}
3

Agora, execute o aplicativo no dispositivo conectado. Crie ou inicie sessão numa conta na aplicação. Se você estiver usando o aplicativo SwiftUI Template, crie alguns itens. Você deverá ver a sincronização de itens com a coleção Item vinculada ao seu aplicativo Atlas App Services.

Em seguida, enquanto deixa o aplicativo em execução no Xcode, envie o aplicativo para o plano de fundo em seu dispositivo. Você deve ver a impressão do console "Agendou com sucesso uma tarefa em segundo plano" e, em seguida, receber um prompt do LLDB.

4

Enquanto o aplicativo estiver em segundo plano, mas ainda em execução no Xcode, insira um novo documento na coleção relevante do Atlas que deve sincronizar com o dispositivo. Alternativamente, altere um valor de um documento existente que você criou a partir do dispositivo. Depois de executar com sucesso a tarefa em segundo plano, você deverá ver esses dados sincronizados com o dispositivo a partir do processo em segundo plano.

Se você estiver utilizando o SwiftUI aplicativo Modelo , poderá localizar documentos relevantes na Atlas Item coleção do seu agrupamento do . Para mais informações sobre como adicionar ou alterar documentos no Atlas, consulte: MongoDB Atlas: Criar, Exibir, Atualizar e Excluir Documentos.

5

Use este comando para executar manualmente a tarefa de plano de fundo no LLDB:

e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"refreshTodoRealm"]

Se você utilizou um identificador diferente para sua tarefa de plano de fundo, substitua refreshTodoRealm pelo identificador da sua tarefa. Isso faz com que a tarefa comece a ser executada imediatamente.

Se feito corretamente, você deverá ver algo como:

2022-11-11 15:09:10.403242-0500 App[1268:196548] Simulating launch for task with identifier refreshTodoRealm
2022-11-11 15:09:16.530201-0500 App[1268:196811] Starting simulated task

Depois de iniciar a tarefa, use o botão Continue program execution no painel de depuração do Xcode para retomar a execução do aplicativo.

6

Depois de aguardar a conclusão da tarefa em segundo plano, mas antes de abrir o aplicativo novamente, ative o Modo Avião no dispositivo. Certifique-se de ter desligado o WiFi. Isso garante que, quando você abrir o aplicativo novamente, ele não iniciará uma nova sincronização e você verá apenas os valores que estão agora no domínio do dispositivo.

7

Abra o aplicativo no dispositivo. Você deve visualizar os dados atualizados que você alterou no Atlas.

Para verificar se as atualizações vieram por meio da tarefa em segundo plano, confirme se você desabilitou a rede com êxito.

Crie uma nova tarefa usando o aplicativo. Você deve visualizar a tarefa no aplicativo, mas ela não deve sincronizar com Atlas. Alternativamente, você pode criar ou alterar dados no Atlas, mas não deve visualizá-los refletidos no dispositivo.

Isso informa que a rede foi desativada com êxito e que os dados atualizados que você vê foram obtidos por meio da tarefa em segundo plano.

Voltar

Gerenciar erros de sincronização