Utilizando Core Data com CloudKit

Aprenda como podemos utilizar estas ferramentas em conjunto

Zewu Chen
Apple Developer Academy | Mackenzie
5 min readApr 15, 2020

--

Lançado em 2019, a Apple disponibilizou o recurso onde podemos utilizar suas ferramentas (Core Data e CloudKit) em conjunto. Mas antes de iniciar, preciso destacar alguns tópicos:

  • Aplicativos que utilizam Core Data podem utilizar o Core Data com o CloudKit, desde que o armazenamento persistente seja um NSSQLiteStoreType e o modelo de dados seja compatível com as limitações do CloudKit;
  • Os aplicativos que usam o CloudKit não podem usar o Core Data em conjunto com contêineres já existentes do CloudKit. Ou seja, se seu aplicativo já o utiliza, você terá que utilizar um novo contêiner;
  • Funciona em iOS com versão 13.0 ou superior;
  • Core Data com CloudKit usa especificamente a record zone privada do usuário.

Pré-Requisitos

  • Conhecimentos básicos de UIKit.
  • Já ter conhecimentos em Core Data
  • Já ter conhecimentos em CloudKit

Passos

  1. Iniciando o projeto
  2. Criando o esquema de dados do Core Data
  3. Realizando o CRUD
  4. Atualizando a UI com as alterações dos dados
  5. Testes
  6. Resultado final

1. Iniciando o projeto

Vamos iniciar um novo projeto no Xcode, marque as opções "Use Core Data" e "Use CloudKit".

Adicione a capability do iCloud e do Background Modes, dentro de background modes habilite "Remote Notifications", isto fará com que o nosso Core Data consiga receber notificações das alterações feitas e puxa-las para nosso armazenamento local.

Caso você já esteja usando o Core Data, você pode adicionar as capabilities acima e mudar o modo de uso do Core Data no próprio AppDelegate. Mude o NSPersistentContainer para NSPersistentCloudKitContainer.

Vamos fazer uma tela simples, montaremos o seguinte esquema:

Para fins didáticos, utilizaremos a ViewController padrão para listar as informações, para outra tela utilizaremos uma denominada DetailViewController

2. Criando o esquema de dados do Core Data

Indo para o arquivo do Core Data, vamos criar uma nova entidade. No meu caso, vou chama-lá de Materia, e ela conterá dois atributos: nome e curso, ambos do tipo String.

Imagem do esquema da entidade

Geraremos a class do Core Data, com a entidade selecionada, vá em Editor-> CreateNSManagedObject Subclass. Ele te dará dois arquivos, eu deixarei apenas um, neste formato:

Caso você esteja adaptando seu Core Data para o CloudKit, marquem a opção "Used with CloudKit" na sua configuration.

Selecionar a opção “Used with CloudKit”

3. Realizando o CRUD

Para iniciar o CRUD, precisaremos de três coisas, o context que sempre usamos no Core Data, uma variável que guardará o resultado dos dados e alguém que delega os dados recebidos/modificados. Os métodos para salvar e deletar são os mesmos que o do Core Data, e a sincronização é feita automática.

Passaremos o context assim que iniciamos o aplicativo, lá no arquivo SceneDelegate instanciamos a ViewController e passamos o context.

Este arquivo foi introduzido o Xcode 11 e com iOS 13, clique aqui para mais detalhes e de quebra, clique aqui para adicioná-lo ao seu projeto.

Vamos puxar os dados!

Crie uma variável do tipo NSFetchedResultsController<ENTIDADE>, responsável pelo dados.

Buscando os dados

Vamos entender o que estamos fazendo:

  • Nesta imagem nós temos o context que já foi inicializado lá no SceneDelegate.
  • Declaramos nossa variável fetchedResultsController para receber os dados buscados.
  • Configuramos nossa função configureFetchedResultsController(), que monta nossa requisição para buscar os dados de uma entidade e filtramos para que a ordem dos resultados volte em ordem crescente por nome.
  • Já no viewWillAppear(), realizamos de fato a busca pelos dados.

Com isto em mente, podemos popular nossa tableView.

Fácil né? Não podemos esquecer de implementar o delegate: NSFetchedResultsControllerDelegate, que tem os métodos quando algum dado for modificado. Dentre eles, nós temos de acordo com a Apple:

You can use controllerWillChangeContent(_:) and controllerDidChangeContent(_:) to bracket updates to a table view whose content is provided by the fetched results controller.

Como exemplo:

Atualizamos a tableView em caso de modificações existentes

Vamos salvar e atualizar!

Quando clicamos em uma célula, vamos para a DetailViewController, no prepareFor(segue_ :) instanciamos e já atribuímos o context e um objeto do tipo matéria se tivermos, desta maneira:

Passando o dado para a outra View

Ao salvar, vamos realizar igual a operação que o Core Data faz normalmente, verificamos se já existe um objeto que foi nos passado pela anterior e atualizamos, caso não haja, criamos um novo objeto.

Salvando/Atualizando um objeto

Por fim, vamos deletar!

Voltamos para a ViewController que estávamos, quando deletarmos um item da tableView, iremos deletá-lo do Core Data também.

Excluindo um objeto

4. Atualizando a UI com as alterações dos dados

Agora precisamos dizer que quando tivermos os dados recebidos, precisaremos atualizar a UI. Neste caso é bem simples, adicionaremos uma linha lá no SceneDelegate:

viewContext.automaticallyMergesChangesFromParent = true

Assim, quando alguma alteração for feita, a UI será recarregada para que a informação seja apresentada.

5. Testes

Para poder realizar os testes, assim como o CloudKit, é necessário que você logue com seu usuário no simulador para que a sincronização dos dados possa ser feita.

6. Resultado final

Abaixo mostro o resultado de como fica o comportamento quando algum dado é modificado.

Você pode encontrar o projeto completo neste link.

Para mais informações, vocês podem consultar a documentação da Apple clicando aqui.
Recomendo que veja os vídeos da WWDC 2019 neste link.
E um site que me ajudou muito a fazer este artigo.
Obrigado ao Andrew Bancroft que me ajudou muito a desenvolver este conhecimento.

--

--

Zewu Chen
Apple Developer Academy | Mackenzie

Desenvolvedor iOS no C6 Bank e Ex-Aluno do Apple Developer Academy | Mackenzie