Core Data — conceitos-chave, NSManagedObject e arquitetura

Autor: IT Sectr Publicado: 2026-03-11 Tempo de leitura: 11 min

Core Data é um framework da Apple para gerenciar um grafo de objetos em aplicações iOS e macOS. Ele fornece persistência de dados, rastreamento de alterações, operações de desfazer e integração com a UI através de NSFetchedResultsController. Segundo a documentação da Apple Developer (2025), Core Data não é um banco de dados — é uma camada de modelagem de objetos que por padrão usa SQLite como armazenamento persistente para carregar e salvar objetos.

Pontos principais

  • Core Data é um framework ORM para iOS/macOS que gerencia um grafo de objetos e os persiste em um armazenamento.
  • NSManagedObjectModel é o esquema de dados que descreve entidades, atributos e relacionamentos em um modelo Core Data.
  • NSManagedObjectContext é uma área de trabalho para criar, ler, atualizar e deletar objetos com rastreamento de alterações.
  • NSPersistentContainer é um ponto de entrada unificado que encapsula o modelo, o contexto e o armazenamento no iOS 10+.
  • NSFetchedResultsController integra Core Data com UITableView/UICollectionView com atualização automática em alterações.

O que é Core Data?

Core Data é um framework de gerenciamento de grafo de objetos e persistência que faz parte do Cocoa Touch SDK da Apple. Ele fornece uma interface orientada a objetos para trabalhar com dados: o desenvolvedor opera com entidades, atributos e relacionamentos, enquanto o Core Data transforma esses objetos em registros de banco de dados relacional sob o capô.

Core Data foi apresentado no Mac OS X 10.4 Tiger (2005) para macOS e portado para iOS 3.0 (2009). Em mais de 20 anos, o framework evoluiu de uma simples camada de abstração sobre SQLite para um stack completo com suporte a sincronização em nuvem através de NSPersistentCloudKitContainer, multithreading através de gerenciamento automático de contextos e carregamento assíncrono via Swift Concurrency.

De acordo com uma pesquisa de desenvolvedores iOS da Slack Community (2025), Core Data é usado em 68% das aplicações iOS comerciais para armazenamento local de dados. Apesar das críticas por sua complexidade e arquitetura em camadas, o framework continua sendo o padrão para aplicações Apple graças à integração estreita com o sistema, custo zero (embutido no SDK) e suporte a sincronização iCloud.

Core Data não é um banco de dados

Um equívoco comum é considerar Core Data um banco de dados. O framework não executa consultas SQL diretamente e não é um SGBD. Core Data é uma camada de gerenciamento de grafo de objetos que pode usar armazenamento SQLite, Binary ou In-Memory para persistência. Analogia: Core Data é como Hibernate ou Entity Framework, mas para o ecossistema Apple, e SQLite por baixo é como MySQL sob Hibernate.

Arquitetura do Core Data: stacks e componentes

O stack do Core Data consiste em quatro componentes interconectados: NSManagedObjectModel (esquema de dados), NSPersistentStoreCoordinator (coordenador de armazenamento), NSManagedObjectContext (contexto de trabalho) e NSPersistentContainer (um contêiner unificado que combina os três desde iOS 10). NSPersistentContainer automatiza a criação e configuração do stack.

Cada componente executa uma função estritamente definida. NSManagedObjectModel carrega o arquivo .xcdatamodeld com as descrições das entidades. NSPersistentStoreCoordinator conecta o modelo ao arquivo físico de armazenamento (SQLite). NSManagedObjectContext fornece uma área temporária para trabalhar com objetos. O Container unifica tudo em uma única chamada de inicialização.

Tipos de armazenamento do Core Data

SQLite (NSSQLiteStoreType) é o armazenamento padrão usado na maioria das aplicações. Os dados são salvos em um único arquivo .sqlite com suporte a transações ACID. Binary (NSBinaryStoreType) é um armazenamento em formato binário para conjuntos de dados pequenos (até algumas centenas de objetos). In-Memory (NSInMemoryStoreType) é um armazenamento temporário em RAM sem persistência em disco, usado para testes e cache.

Tipo de armazenamentoFormatoDesempenhoQuando usar
SQLite.sqliteAltoOpção padrão para produção
Binary.binaryMédioConjuntos de dados pequenos
In-MemoryRAMMáximoTestes, cache, dados temporários
CloudKitiCloudDepende da redeSincronização entre dispositivos

O tipo de armazenamento é definido com uma única linha ao inicializar NSPersistentStoreDescription. O desenvolvedor pode mudar de SQLite para In-Memory para testes unitários ou para CloudKit para sincronização iCloud sem alterar o código de manipulação de objetos — Core Data abstrai as diferenças entre tipos de armazenamento através de uma API de contexto unificada.

NSManagedObject e NSManagedObjectContext

NSManagedObject é a classe base para todos os objetos Core Data, representando um único registro de entidade. Cada managed object tem um NSManagedObjectID único (identificador persistente), está vinculado a um contexto e rastreia suas alterações via KVO (Key-Value Observing). Desenvolvedores criam subclasses de NSManagedObject para definir propriedades tipadas da entidade.

NSManagedObjectContext é o componente central do Core Data que fornece uma área de trabalho para todas as operações com objetos. O contexto rastreia adições, exclusões e alterações (change tracking), suporta desfazer operações via undoManager e mescla automaticamente alterações de outros contextos ao receber notificações de salvamento.

Segurança de threads em contextos

A regra de filas privadas: NSManagedObjectContext é criado com .privateQueueConcurrencyType ou .mainQueueConcurrencyType. O contexto principal está vinculado à thread principal da UI, enquanto contextos privados executam em filas de fundo. Cada contexto deve ser usado apenas em sua própria fila — acessar um managed object de outra thread causa um crash. parentContext permite organizar uma hierarquia de contextos para escritas assíncronas.

swift
struct CoreDataStack {
    let container: NSPersistentContainer

    init(name: String) {
        container = NSPersistentContainer(name: name)
        container.loadPersistentStores { _, error in
            if let error = error {
                fatalError("Failed to load store: \(error)")
            }
        }
        container.viewContext.automaticallyMergesChangesFromParent = true
    }

    func backgroundContext() -> NSManagedObjectContext {
        let context = container.newBackgroundContext()
        context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
        return context
    }
}

NSPersistentContainer cria automaticamente viewContext (main queue) e fornece newBackgroundContext() para operações em segundo plano. Definir automaticallyMergesChangesFromParent = true faz o viewContext capturar automaticamente as alterações dos contextos em segundo plano quando salvam, atualizando a UI sem necessidade de consultar novamente os dados manualmente.

Persistent Store e SQLite

NSPersistentStoreCoordinator gerencia o armazenamento físico de dados: abre o arquivo, cria tabelas SQLite baseadas no modelo e realiza migrações quando o esquema muda. Ao inicializar NSPersistentStoreDescription com NSSQLiteStoreType, Core Data cria um arquivo SQLite com um esquema correspondente ao modelo .xcdatamodeld.

Core Data não usa consultas SQL padrão via SELECT/INSERT/UPDATE. Em vez disso, ele gera comandos SQL internos baseados no modelo e nas consultas feitas através de NSFetchRequest. O desenvolvedor pode ativar o log SQL com o argumento de inicialização -com.apple.CoreData.SQLDebug 1 para depurar o desempenho das consultas.

Migrações do Core Data

Migração leve (Lightweight Migration) é um processo automático de atualização do esquema SQLite ao adicionar novos atributos, alterar flags optional/required ou renomear com renamingID. Migração pesada é necessária para mudanças radicais de esquema como mesclar ou dividir entidades, e é realizada através de um NSMigrationManager personalizado.

swift
let description = NSPersistentStoreDescription()
description.url = FileManager.default
    .urls(for: .documentDirectory, in: .userDomainMask)
    .first?
    .appendingPathComponent("Model.sqlite")
description.setOption(true as NSNumber,
    forKey: NSMigratePersistentStoresAutomaticallyOption)
description.setOption(true as NSNumber,
    forKey: NSInferMappingModelAutomaticallyOption)

let container = NSPersistentContainer(name: "AppModel")
container.persistentStoreDescriptions = [description]
container.loadPersistentStores { _, error in
    if let error = error { print("Migration error: \(error)") }
}

Configurar a migração automática via NSMigratePersistentStoresAutomaticallyOption e NSInferMappingModelAutomaticallyOption permite que Core Data atualize independentemente o arquivo SQLite ao adicionar atributos ou entidades em uma nova versão do modelo. Se a migração não for possível, o store coordinator lança um erro com a descrição do motivo — o desenvolvedor deve então implementar uma migração personalizada via NSMigrationManager.

Core Data na prática: código e exemplos

NSFetchRequest é a ferramenta principal para buscar objetos do Core Data. Uma requisição contém o nome da entidade, predicado (filtro), descritores de ordenação, limite e deslocamento. O resultado é retornado como um array de NSManagedObject ou subclasses tipadas. NSPredicate suporta condições complexas com AND, OR, IN, LIKE e subconsultas.

NSBatchDeleteRequest é uma forma eficiente de deletar objetos em lote sem carregar cada um na memória. A requisição executa no nível SQLite, ignorando o managed object context, e só atualiza o contexto após a conclusão. Requisições batch similares existem para atualizar (NSBatchUpdateRequest) e inserir (NSBatchInsertRequest).

Exemplo de operações CRUD

CRUD (Create, Read, Update, Delete) no Core Data é realizado através de métodos do contexto: insert, fetch, save e delete. Todas as alterações são temporárias até que context.save() seja chamado — este método salva as alterações no armazenamento persistente SQLite. Em erro de salvamento, o contexto permanece em seu estado modificado para uma nova tentativa.

swift
let context = container.viewContext

// Criar
let user = User(context: context)
user.id = 42
user.name = "Alice"

// Ler
let request = User.fetchRequest()
request.predicate = NSPredicate(format: "name CONTAINS %@", "Ali")
request.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
let results = try context.fetch(request)

// Atualizar
results.first?.name = "Alice Updated"

// Excluir
if let first = results.first { context.delete(first) }

// Salvar
try context.save()

Salvar o contexto (context.save()) é uma operação crítica. Se save não for chamado, todas as alterações permanecem apenas em memória. O contexto rastreia o estado hasChanges, que pode ser verificado antes de salvar. Para operações em segundo plano, use newBackgroundContext com seu próprio salvamento, e para a UI, use viewContext com salvamento automático por temporizador ou quando o aplicativo entra em segundo plano.

Melhores práticas do Core Data

Primeira prática — use NSPersistentCloudKitContainer para sincronizar dados entre dispositivos do usuário via iCloud. A sincronização em nuvem é ativada adicionando a opção CloudKit à descrição do persistent store. Core Data gerencia automaticamente os conflitos de sincronização e mescla alterações de outros dispositivos.

Segunda prática — evite fetchRequest sem predicado em tabelas grandes. Cada fetch incondicional carrega todos os objetos da entidade na memória, levando a alto consumo de RAM e lentidão da UI. Sempre use predicados e limites. Para paginação, use fetchLimit e fetchOffset no NSFetchRequest.

Terceira prática — configure mergePolicy para resolver conflitos em acesso multithread. NSMergeByPropertyObjectTrumpMergePolicy atualiza propriedades conflitantes do último contexto salvo. NSRollbackMergePolicy descarta alterações do contexto atual em conflito. A escolha da política depende da lógica de negócio da aplicação.

Quarta prática — use NSFetchedResultsController para integração com tabelas e coleções. Ele se inscreve automaticamente nas notificações NSManagedObjectContextDidSave, carrega apenas objetos necessários (faulting) e notifica o delegado sobre inserções, exclusões e movimentos com os index paths apropriados para animação de UITableView.

Desempenho: Prefetching e Faulting

Faulting é o mecanismo de carregamento preguiçoso do Core Data. Um managed object retornado por uma fetch request está em estado fault — seus atributos não estão totalmente carregados, apenas o identificador. O carregamento completo (fire fault) ocorre no primeiro acesso a qualquer atributo. Relationship prefetching (setRelationshipKeyPathsForPrefetching) carrega objetos relacionados com antecedência, evitando consultas N+1.

swift
extension UserRepository {
    func fetchUsersWithPosts() throws -> [User] {
        let request = User.fetchRequest()
        request.predicate = NSPredicate(format: "isActive == YES")
        request.relationshipKeyPathsForPrefetching = ["posts"]
        request.returnsObjectsAsFaults = false
        request.fetchBatchSize = 20

        let context = container.viewContext
        return try context.fetch(request)
    }
}

fetchBatchSize = 20 faz Core Data carregar dados em lotes de 20 objetos (para exibição em tela), sem carregar toda a tabela de uma vez. A flag returnsObjectsAsFaults = false garante que todos os atributos do usuário sejam carregados imediatamente, útil para exibição direta. O prefetching do relacionamento “posts” evita consultas separadas para cada usuário ao acessar as postagens.

Perguntas frequentes

Core Data é um banco de dados?

Não, Core Data é um framework de gerenciamento de grafo de objetos. Ele fornece uma API para trabalhar com objetos, rastrear alterações e persisti-los. O banco de dados sob o capô do Core Data (SQLite por padrão) não deve ser confundido com o próprio framework. Core Data é um ORM, não um SGBD.

Core Data pode ser usado sem SQLite?

Sim, Core Data suporta três tipos de armazenamento: SQLite, Binary e In-Memory. O tipo de armazenamento é definido via NSPersistentStoreDescription. O armazenamento In-Memory não persiste dados em disco e é adequado para testes unitários. O armazenamento Binary é um formato legado para conjuntos compactos de objetos.

Como migrar Core Data para uma nova versão do modelo?

Para migração leve, ative NSMigratePersistentStoresAutomaticallyOption e NSInferMappingModelAutomaticallyOption. Para alterações complexas, crie um Mapping Model (.xcmappingmodel) via Xcode. O armazenamento CloudKit (NSPersistentCloudKitContainer) suporta migrações automaticamente ao sincronizar o esquema com o servidor iCloud.

Como o Core Data é diferente do SwiftData?

SwiftData é um novo framework da Apple (iOS 17+) construído sobre Core Data usando Swift Macros e Swift Concurrency. SwiftData tem uma sintaxe mais simples: entidades são descritas com o macro @Model, contexto com @Environment(\.modelContext). Sob o capô, SwiftData usa o mesmo stack Core Data e SQLite.

Como depurar consultas lentas do Core Data?

Ative o argumento de inicialização -com.apple.CoreData.SQLDebug 1 — Core Data exibirá todas as consultas SQL e suas durações no console do Xcode. Para perfilamento, use Instruments com o template Core Data, que mostra o número de fault requests, tempos de carregamento de objetos e duração do salvamento do contexto.

Resumo

  • Core Data é um framework de gerenciamento de grafo de objetos e persistência para iOS e macOS, usando SQLite como armazenamento padrão.
  • O stack Core Data inclui NSManagedObjectModel, NSPersistentStoreCoordinator, NSManagedObjectContext e NSPersistentContainer para configuração unificada.
  • NSManagedObjectContext é uma área de trabalho com rastreamento de alterações, suporte a desfazer e mesclagem automática de contextos em segundo plano.
  • NSFetchRequest com NSPredicate e prefetching de relacionamentos é a principal ferramenta de busca, otimizada via batch size e faulting.
  • Migração leve atualiza automaticamente o esquema SQLite ao adicionar atributos e entidades em uma nova versão do modelo.
  • NSPersistentCloudKitContainer adiciona sincronização iCloud entre dispositivos do usuário com resolução automática de conflitos.
  • Recomendação — use Core Data para aplicações iOS com modelos de objetos hierárquicos; para armazenamento local simples, considere GRDB ou SwiftData.

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