Como depurar problemas de sync do CloudKit usando o Console.app

Mario
Mario
24 de janeiro de 2026

O problema

Cenário: um app multi-plataforma (macOS + iOS) usando SwiftData com CloudKit sync. Tudo funciona perfeitamente no iPhone. No Mac, o sync está completamente quebrado:

  • Tarefas editadas no Mac não sincronizam
  • Pastas criadas no Mac nunca chegam ao CloudKit
  • Nenhum erro visível no app

O app não apresenta crashes nem mensagens de erro. Do ponto de vista do usuário, simplesmente "não funciona".


Console.app: a ferramenta esquecida

O macOS inclui uma ferramenta poderosa para diagnóstico que muitos desenvolvedores ignoram: o Console.app (/Applications/Utilities/Console.app).

Como usar

  1. Abra o Console.app
  2. Na barra lateral, selecione seu Mac
  3. No campo de busca, filtre pelo nome do seu app
  4. Reproduza o problema no app
  5. Observe os logs em tempo real

O que procurar

Erros de CloudKit aparecem com prefixos como:

  • CoreData+CloudKit
  • CKScheduler
  • CKContainer

Descobrindo a causa raiz

Ao filtrar os logs pelo nome do app, encontrei o erro:

"Cannot create or modify field 'CD_dueDate' in record 'CD_Folder' in production schema"

O problema ficou claro: o schema de produção do CloudKit estava desatualizado. O modelo Folder possuía uma propriedade dueDate adicionada após o schema original ter sido enviado para produção.

CloudKit não migra automaticamente schemas em produção. Resultado: 399 operações de sync falharam silenciosamente.


Solução manual: atualizar o schema

A correção imediata requer acesso ao CloudKit Dashboard:

  1. Acessar icloud.developer.apple.com
  2. Selecionar o container do app
  3. Ir em Schema -> Record Types -> CD_Folder
  4. Adicionar o campo CD_dueDate (tipo: Date/Time)
  5. Clicar em Deploy Schema Changes

Após reiniciar o app, o sync voltou a funcionar.


O problema recorrente

A solução manual resolve o problema pontual, mas não evita recorrências. Toda vez que um novo campo é adicionado ao modelo Swift, o mesmo problema pode ocorrer.

CloudKit só cria colunas no schema quando recebe registros com esses campos preenchidos. Adicionar propriedades aos modelos Swift não atualiza automaticamente o schema do CloudKit.


Solução automatizada: schema seeding

Criei uma ferramenta de debug que força a criação das colunas no CloudKit. A ideia é simples:

  1. Criar registros temporários com todos os campos preenchidos
  2. Salvar no contexto (força CloudKit a criar as colunas)
  3. Aguardar sync
  4. Remover os registros de teste
  5. Fazer deploy do schema para produção
# if DEBUG
enum CloudKitSchemaSeed {
    @MainActor
    static func seedSchema(context: ModelContext) throws {
        let folder = Folder(
            title: "__SCHEMA_SEED_FOLDER__",
            color: "#FF0000",
            startDate: Date(),
            customIconSymbolName: "star.fill"
            // ... todos os campos
        )
        context.insert(folder)
        try context.save()
    }
}
# endif

A ferramenta fica disponível apenas em builds de debug, acessível via Settings -> Developer.


Descoberta: campos _ckAsset

Durante os testes, um novo erro apareceu no Console.app:

"Cannot create or modify field 'CD_taskDescriptionData_ckAsset' in record 'CD_Task' in production schema"

CloudKit converte automaticamente campos Data maiores que 1MB para Assets. Quando isso acontece, cria um campo adicional com sufixo _ckAsset.

Se esse campo não existe no schema de produção, o sync falha.

Solução

O seed deve incluir dados grandes para forçar a criação do campo Asset:

private static func createLargeData() -> Data {
    let chunk = "Schema seed data for CloudKit asset field creation. "
    let repeatedString = String(repeating: chunk, count: 40_000) // ~2MB
    return Data(repeatedString.utf8)
}

// No seed:
task.taskDescriptionData = createLargeData()

Checklist de verificação

Após corrigir problemas de schema:

  • Editar item no Mac -> verificar propagação para iPhone
  • Editar item no iPhone -> verificar propagação para Mac
  • Criar novo item no Mac -> verificar se aparece no iPhone
  • Deletar item no Mac -> verificar se some do iPhone

Lições aprendidas

  1. Console.app é essencial para diagnosticar problemas em apps de produção. Erros que o app não exibe para o usuário ficam visíveis nos logs do sistema.

  2. CloudKit não migra schemas automaticamente em produção. Mudanças no modelo de dados requerem deploy manual ou uso de ferramentas de seeding.

  3. Campos Data grandes viram Assets. Se o app pode armazenar dados maiores que 1MB, o campo _ckAsset correspondente deve existir no schema.

  4. Sync funcionar em um dispositivo não garante funcionamento em outro. O iPhone tinha o schema correto; o Mac estava tentando criar campos que não existiam em produção.


Referências