Preciso criar NSManagedObject
instâncias, fazer algumas coisas com elas e, em seguida, jogá-las no lixo ou armazená-las em sqlite db. O problema é que não consigo criar instâncias de NSManagedObject
não conectado a NSManagedObjectContext
e isso significa que tenho que limpar de alguma forma depois de decidir que não preciso de alguns dos objetos em meu banco de dados.
Para lidar com isso, eu criei um armazenamento na memória usando o mesmo coordenador e estou colocando objetos temporários lá usando assignObject:toPersistentStore.
Agora, como posso garantir que esses objetos temporários não cheguem aos dados, que eu busco do comum ao contexto de ambas as lojas? Ou devo criar contextos separados para tal tarefa?
UPD:
Agora estou pensando em criar um contexto separado para armazenamento na memória. Como faço para mover objetos de um contexto para outro? Apenas usando [context insertObject:]? Funcionará bem nesta configuração? Se eu inserir um objeto do gráfico de objetos, o gráfico inteiro também é inserido no contexto?
fonte
Respostas:
NOTA: Esta resposta é muito antiga. Veja os comentários para a história completa. Minha recomendação mudou desde então e eu não recomendo mais o uso de
NSManagedObject
instâncias não associadas . Minha recomendação atual é usarNSManagedObjectContext
instâncias filho temporárias .Resposta Original
A maneira mais fácil de fazer isso é criar suas
NSManagedObject
instâncias sem um associadoNSManagedObjectContext
.Então, quando você quiser salvá-lo:
fonte
iOS5 oferece uma alternativa mais simples para a resposta de Mike Weller. Em vez disso, use uma criança NSManagedObjectContext . Ele elimina a necessidade de trampolim por meio do NSNotificationCenter
Para criar um contexto filho:
Em seguida, crie seus objetos usando o contexto filho:
As alterações são aplicadas apenas quando o contexto filho é salvo. Portanto, para descartar as alterações, apenas não salve.
Ainda existe uma limitação nos relacionamentos. ou seja, você não pode criar relacionamentos com objetos em outros contextos. Para contornar isso, use objectID's para obter o objeto do contexto filho. por exemplo.
Observe que salvar o contexto filho aplica as alterações ao contexto pai. Salvar o contexto pai persiste as alterações.
Consulte a sessão 214 do wwdc 2012 para obter uma explicação completa.
fonte
moc
no terceiro trecho? ÉchildContext
oumyMangedObjectContext
?NSManagedObject
já fornece o relevanteNSManagedObjectContext
, você pode automatizar a escolha do contexto:NSManagedObject* objectRelatedContextually = [objectWithRelationship.managedObjectContext objectWithID:objectRelated.objectID];
e entãoobjectWithRelationship.relationship = objectRelatedContextually;
.A maneira correta de conseguir esse tipo de coisa é com um novo contexto de objeto gerenciado. Você cria um contexto de objeto gerenciado com o mesmo armazenamento persistente:
Em seguida, você adiciona novos objetos, os transforma, etc.
Quando chega a hora de salvar, você precisa chamar [tempContext save: ...] no tempContext e manipular a notificação de salvamento para mesclar isso ao seu contexto original. Para descartar os objetos, basta liberar este contexto temporário e esquecê-lo.
Então, quando você salva o contexto temporário, as alterações são mantidas na loja, e você só precisa colocar essas alterações de volta em seu contexto principal:
Essa também é a maneira pela qual você deve lidar com operações de dados centrais multithread. Um contexto por thread.
Se você precisa acessar objetos existentes a partir deste contexto temporário (para adicionar relações, etc.), você precisa usar o ID do objeto para obter uma nova instância como esta:
Se você tentar usar um
NSManagedObject
no contexto errado, obterá exceções ao salvar.fonte
NSManagedObjectContext
é caro tanto em memória quanto em CPU. Eu sei que isso estava originalmente em alguns dos exemplos da Apple, mas eles atualizaram e corrigiram esses exemplos.Criar objetos temporários de contexto nulo funciona bem até que você realmente tente ter um relacionamento com um objeto cujo contexto! = Nulo!
certifique-se de que você concorda com isso.
fonte
O que você está descrevendo é exatamente para que
NSManagedObjectContext
serve.Do Core Data Programming Guide: Core Data Basics
E Guia de Programação de Dados Principais: Validação de Objeto Gerenciado
NSManagedObjectContext
s são projetados para serem leves. Você pode criá-los e descartá-los à vontade - é o coordenador de armazenamento persistente e suas dependências que são "pesadas". Um único coordenador de loja persistente pode ter muitos contextos associados a ele. No modelo de confinamento de thread mais antigo e obsoleto, isso significaria definir o mesmo coordenador de armazenamento persistente em cada contexto. Hoje, isso significaria conectar contextos aninhados a um contexto raiz que está associado ao coordenador de armazenamento persistente.Crie um contexto, crie e modifique objetos gerenciados dentro desse contexto. Se você deseja mantê-los e comunicar essas mudanças, salve o contexto. Caso contrário, descarte-o.
Tentar criar objetos gerenciados independentes de um
NSManagedObjectContext
é procurar problemas. Lembre-se de que o Core Data é basicamente um mecanismo de controle de alterações para um gráfico de objeto. Por causa disso, os objetos gerenciados são realmente parte do contexto do objeto gerenciado . O contexto observa seu ciclo de vida e, sem o contexto, nem todas as funcionalidades do objeto gerenciado funcionarão corretamente.fonte
Dependendo do uso do objeto temporário, há algumas ressalvas às recomendações acima. Meu caso de uso é que desejo criar um objeto temporário e vinculá-lo a visualizações. Quando o usuário opta por salvar este objeto, desejo configurar relacionamentos com o (s) objeto (s) existente (s) e salvá-lo. Quero fazer isso para evitar a criação de um objeto temporário para conter esses valores. (Sim, eu poderia apenas esperar até que o usuário salve e, em seguida, pegue o conteúdo da visualização, mas estou colocando essas visualizações dentro de uma tabela e a lógica para fazer isso é menos elegante.)
As opções para objetos temporários são:
1) (Preferencial) Crie o objeto temporário em um contexto filho. Isso não funcionará porque estou vinculando o objeto à IU e não posso garantir que os acessadores do objeto sejam chamados no contexto filho. (Não encontrei nenhuma documentação que indique o contrário, portanto, devo assumir.)
2) Crie o objeto temporário com contexto de objeto nulo. Isso não funciona e resulta em perda / corrupção de dados.
Minha solução: Resolvi isso criando o objeto temporário com contexto de objeto nulo, mas quando salvo o objeto, em vez de inseri-lo como # 2, copio todos os seus atributos em um novo objeto que criei no contexto principal. Eu criei um método de suporte em minha subclasse NSManagedObject chamado cloneInto: que me permite copiar atributos e relacionamentos facilmente para qualquer objeto.
fonte
Para mim, a resposta de Marcus não funcionou. Aqui está o que funcionou para mim:
então, se eu decidir salvá-lo:
Também não devemos esquecer de liberá-lo
fonte
Estou reescrevendo esta resposta para o Swift, pois todas as perguntas semelhantes para o Swift redirecionam para esta pergunta.
Você pode declarar o objeto sem qualquer ManagedContext usando o código a seguir.
Posteriormente, para salvar o objeto, você pode inseri-lo no contexto e salvá-lo.
fonte