Core Data — o que é, modelo de dados e como funciona

Autor: IT Sectr Publicado: 2026-05-04 Tempo de leitura: 8 min

Core Data é um framework de gerenciamento de dados da Apple que fornece mapeamento objeto-relacional para iOS, macOS, tvOS e watchOS. Ele automatiza a salvamento, recuperação e filtragem de objetos no aplicativo, funcionando sobre SQLite, XML ou armazenamento binário. De acordo com a Apple Core Data Documentation, o framework usa os conceitos de Managed Object Context e NSPersistentContainer para gerenciar a pilha de persistência.

Principais pontos

  • Core Data — framework da Apple para gerenciamento objeto-relacional de dados em aplicações.
  • NSManagedObjectModel — descrição do esquema de dados: Entity, Attributes e Relationships.
  • NSManagedObject — objeto que corresponde a um registro no armazenamento Core Data.
  • NSManagedObjectContext — área de trabalho para criar, ler e salvar objetos.
  • NSPersistentContainer — pilha unificada que combina modelo, contexto e coordenador de armazenamento.

O que é Core Data e seu papel no iOS

Core Data é um framework de gerenciamento de grafo de objetos e persistência que faz parte do Cocoa Touch. Ao contrário do que se pensa, Core Data não é um banco de dados, mas uma camada de gerenciamento de objetos que pode usar SQLite como um de seus armazenamentos. A principal tarefa do Core Data é rastrear alterações de objetos, gerenciar seu ciclo de vida e sincronizar o estado com o disco.

O framework fornece um grafo de objetos onde cada Managed Object é monitorado pelo contexto para detectar alterações. Ao salvar, todos os objetos modificados, adicionados e excluídos são confirmados no armazenamento persistente em uma única transação. Isso elimina a necessidade do desenvolvedor escrever consultas SQL e gerenciar transações manualmente.

De acordo com as estatísticas da Swift Developer Survey (2025), o Core Data é usado em 52% dos aplicativos iOS que trabalham com dados locais. Apesar do surgimento de alternativas modernas (SwiftData, Realm), o Core Data continua sendo o framework principal em projetos Apple existentes devido à sua maturidade e integração profunda com o sistema.

Use Core Data para projetos com modelo de dados de complexidade média, onde são necessários relacionamentos entre objetos, desfazer alterações e cache automático através do mecanismo de faulting.

A arquitetura do Core Data é construída em torno do conceito de Managed Object Context — uma área de trabalho que rastreia todas as alterações de objetos. O contexto suporta desfazer/refazer através do NSUndoManager integrado, permitindo implementar rascunhos e cancelamento de ações sem salvar manualmente snapshots de estado. Ao chamar save(), o contexto confirma todas as alterações em uma única transação no armazenamento persistente, garantindo atomicidade e consistência dos dados.

Modelo de dados: Entity, Attributes, Relationships

O modelo de dados do Core Data é definido no arquivo .xcdatamodeld — o editor visual do Xcode onde todas as Entity, seus atributos e relacionamentos são descritos. Na compilação, o modelo é serializado em .momd e carregado através do NSManagedObjectModel.

Entity e Attributes

Entity é uma descrição de tipo de dados, semelhante a uma tabela em SQL. Cada Entity contém um conjunto de Attributes — campos nomeados com tipo de dados (String, Integer, Date, Boolean, Data). Ao contrário do Room, o Core Data requer seleção explícita de tipo para cada atributo através do editor de modelos.

Relationships

Relationship é uma conexão entre Entity, semelhante a uma chave estrangeira em SQL. Core Data suporta todos os tipos de relacionamentos: um-para-um, um-para-muitos e muitos-para-muitos. Para cada relacionamento é configurada uma Delete Rule (Cascade, Nullify, Deny) — o comportamento ao excluir o objeto relacionado.

Delete RuleComportamento ao excluirExemplo de uso
CascadeExclui todos os objetos relacionadosExcluir um pedido junto com seus itens
NullifyAnula o relacionamento inversoExcluir um autor sem excluir livros
DenyBloqueia a exclusão se houver objetos relacionadosProteger contra exclusão de uma categoria com produtos

Escolher uma Delete Rule é crítico para a integridade dos dados: Cascade sem verificação pode excluir um terço do banco de dados, enquanto Deny pode bloquear a operação com um erro pouco claro. Em código de produção, recomenda-se Nullify com tratamento manual de registros órfãos.

No editor de modelos do Xcode, o desenvolvedor pode definir não apenas Entity e atributos, mas também constraints (restrições de unicidade), índices para acelerar consultas e valores padrão para atributos. Todas as alterações do modelo são compiladas em um arquivo .momd, que é carregado durante a inicialização do NSPersistentContainer. O versionamento de modelo (Model Versioning) permite manter múltiplas versões do esquema e realizar migração entre elas.

Pilha Core Data: PersistentContainer e Context

NSPersistentContainer é um objeto único que gerencia a pilha Core Data desde iOS 10 e macOS 10.12. Ele encapsula NSManagedObjectModel, NSPersistentStoreCoordinator e NSManagedObjectContext, automatizando o carregamento do modelo e a configuração do armazenamento. Para versões mais antigas, a pilha era construída manualmente, mas isso não é mais recomendado.

swift
let container = NSPersistentContainer(name: "DataModel")
container.loadPersistentStores { _, error in
    if let error { fatalError("Core Data load failed: \(error)") }
}
let context = container.viewContext

viewContext é o contexto principal vinculado à thread principal. Todas as leituras e atualizações de interface são feitas através dele. Para desempenho, recomenda-se realizar a escrita de dados em um contexto filho em segundo plano com sincronização posterior.

NSPersistentStoreCoordinator

O coordenador NSPersistentStoreCoordinator conecta o modelo ao armazenamento físico em disco. Core Data suporta vários tipos de armazenamento: SQLite (recomendado), Binary e In-Memory. O armazenamento SQLite suporta migrações, backup incremental e resistência a falhas durante operações de escrita.

NSFetchRequest e trabalho com dados

NSFetchRequest é um objeto que descreve uma consulta ao armazenamento Core Data. Ele contém o nome da Entity, o predicado de filtro, os descritores de ordenação e as configurações de busca. A consulta é executada através de context.fetch(), que retorna um array de NSManagedObject.

swift
let request = NSFetchRequest<User>(entityName: "User")
request.predicate = NSPredicate(format: "age >= %d", 18)
request.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
request.fetchLimit = 50

let results = try context.fetch(request)

NSPredicate suporta condições complexas: LIKE, IN, BETWEEN, CONTAINS[c] (insensível a maiúsculas/minúsculas), SUBQUERY para consultas aninhadas em Entity relacionadas. Core Data também suporta NSFetchedResultsController — uma classe para carregamento reativo de dados em UITableView, que rastreia automaticamente as alterações e atualiza a tabela com seções animadas.

Core Data em ambiente multithread

Trabalhar com Core Data em uma aplicação multithread requer conformidade estrita com as regras: NSManagedObject não pode ser passado diretamente entre threads. Cada thread (ou fila) deve usar seu próprio contexto. A abordagem principal é criar um NSManagedObjectContext filho com uma fila privada (NSPrivateQueueConcurrencyType) para escrita e viewContext para leitura.

O contexto filho salva no pai, e então o pai salva no armazenamento em disco. Isso garante que as alterações não bloqueiem a thread principal e que a interface do usuário veja sempre um estado consistente através de mergeChanges ou atualização automática do viewContext ao salvar.

Core Data usa faulting — um mecanismo de carregamento preguiçoso para objetos relacionados. Ao buscar um User sem solicitar seus endereços, os objetos Address relacionados não são carregados até que sejam acessados via notação de ponto. Faulting economiza memória e acelera o carregamento, mas pode causar acessos inesperados ao disco na thread principal se o acesso não for controlado em contextos de segundo plano.

Para multithreading eficiente, use NSBatchInsertRequest e NSBatchDeleteRequest para inserções e exclusões em massa sem carregar objetos na memória — isso é crítico para sincronização de dados com o servidor.

As operações em lote são executadas diretamente no nível do NSPersistentStoreCoordinator, ignorando o contexto e o grafo de objetos. Isso permite inserir 10.000 registros em milissegundos sem criar 10.000 instâncias de NSManagedObject na memória. Após executar uma solicitação em lote, o contexto deve ser atualizado via mergeChangesFromContextDidSaveNotification para que a interface reflita os novos dados. A Apple recomenda operações em lote para carregamento inicial de dados e sincronização noturna com o servidor.

Para rastreamento de alterações no Core Data, usa-se NSPersistentHistoryTracking — um mecanismo que registra cada transação (inserção, atualização, exclusão) em um histórico separado. Ativar o histórico permite sincronizar dados entre diferentes processos e aplicações que trabalham com o mesmo arquivo SQLite, por exemplo entre a aplicação principal e uma Notification Service Extension. A ativação é feita através do NSPersistentStoreDescription com a flag persistentHistoryTrackingKey, e a leitura através do NSPersistentHistoryChangeRequest com filtragem por data e tipo de transação.

Para depuração e análise de desempenho do Core Data, usa-se a ferramenta Core Data Profiler do conjunto Instruments no Xcode no macOS. Ela mostra todas as operações de busca, inserção, exclusão e salvamento com a duração de cada operação e o número de objetos carregados em tabelas e gráficos de linha do tempo. O desenvolvedor pode identificar áreas problemáticas: múltiplas buscas da mesma consulta (falta de cache), vazamentos de objetos fault durante a rolagem da tabela ou bloqueio da thread principal devido ao carregamento síncrono de entidades relacionadas. Recomenda-se executar a criação de perfil em um dispositivo real e não em um simulador, pois o desempenho do simulador não reflete o comportamento real da aplicação em um iPhone ou iPad.

Perguntas frequentes

Como o Core Data difere do SQLite?

Core Data não é um banco de dados, mas uma camada de gerenciamento de objetos que pode usar SQLite como armazenamento. Ao contrário do SQLite puro, Core Data rastreia alterações de objetos, gerencia desfazer e fornece um grafo de objetos com faulting e cache. SQLite dá mais controle sobre as consultas, mas requer escrever SQL e gerenciar transações manualmente.

Como realizar a migração de esquema do Core Data?

Core Data suporta migração leve (Lightweight Migration) para alterações não destrutivas: adicionar um atributo, renomear, definir um valor padrão. Para alterações complexas, um Mapping Model é criado. A migração leve é ativada pela flag shouldMigrateAutomatically no NSPersistentStoreDescription.

Pode-se usar Core Data com SwiftUI?

Sim, Core Data integra-se com SwiftUI através do wrapper @FetchRequest para consultas e @ObservedObject para assinatura de alterações. SwiftUI atualiza automaticamente a View quando um ManagedObject muda, tornando Core Data e SwiftUI uma pilha compatível para gerenciamento de estado.

O que é um fault no Core Data?

Um fault é um placeholder leve no grafo do Core Data que não contém os dados do objeto relacionado. Quando um fault é definido (via refreshObject:), os dados são descarregados da memória. Quando uma propriedade é acessada, o fault é automaticamente preenchido com dados do armazenamento — este é um mecanismo de carregamento preguiçoso que otimiza o uso de memória.

Como testar código Core Data?

Para testes, use o tipo de armazenamento In-Memory: NSPersistentStoreDescription com NSInMemoryStoreType. O contêiner é criado com o modelo do bundle de teste. Após cada teste, exclua todos os objetos ou recrie o contêiner — isso garante o isolamento dos casos de teste entre si.

Resumo

  • Core Data é um framework de gerenciamento de grafo de objetos que usa SQLite como armazenamento padrão.
  • NSManagedObjectModel descreve o esquema: Entity, Attributes, Relationships e Delete Rules.
  • NSPersistentContainer combina modelo, coordenador e viewContext em uma pilha unificada.
  • NSFetchRequest com NSPredicate e NSSortDescriptor forma consultas flexíveis ao armazenamento.
  • Multithreading requer contextos separados: um contexto filho para escrita e viewContext para leitura.
  • Faulting adia o carregamento de objetos relacionados até o primeiro acesso, economizando memória.
  • Lightweight Migration lida automaticamente com alterações de esquema não destrutivas sem perda de dados.

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também