Como obter o objeto Core Data a partir de um ID de objeto específico?

120

É possível obter facilmente o ID de um objeto no Core Data usando o seguinte código:

NSManagedObjectID *moID = [managedObject objectID];

No entanto, existe uma maneira de obter um objeto do armazenamento de dados principal, fornecendo a ele um ID de objeto específico? Eu sei que posso fazer isso usando um NSFetchRequest, como este:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Document" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(objectID = %@)", myObjectID];
[fetchRequest setPredicate:predicate];

No entanto, gostaria de fazê-lo de uma maneira que não inicie sua própria solicitação de busca. Alguma ideia?

Jason
fonte
Porém, com a forma de solicitação de busca, você pode definir propriedades ou relações a serem pré-buscadas, o que proporcionará uma excelente eficiência, em vez de muitas outras consultas à medida que você acessa as coisas.
Malhal

Respostas:

208

Você quer:

-(NSManagedObject *)existingObjectWithID:(NSManagedObjectID *)objectID
                                   error:(NSError **)error

Busca o objeto da loja que possui esse ID ou nulo, se ele não existir.

(Lembre-se: existem dois métodos no NSManagedObjectContext com nomes semelhantes que me deram uma surra. Para ajudar a mantê-los em ordem, veja o que os outros dois fazem:

-(NSManagedObject *)objectWithID:(NSManagedObjectID *)objectID

... criará um objeto de falha com o ID do objeto fornecido, se esse objeto realmente existe ou não no armazenamento. Se não existir, tudo o que acionar a falha falhará, a menos que você insira o objeto primeiro com o NSManagedObjectContext insertObject:. O único uso que encontrei para isso é copiar objetos de uma loja para outra, preservando os ObjectIDs.

-(NSManagedObject *)objectRegisteredForID:(NSManagedObjectID *)objectID

... retornará o objeto que possui esse ID, se ele foi buscado na loja por este managedObjectContext. Se alguém souber para que serve esse método, comente.)

[eta .: Outra diferença importante entre o primeiro método e os outros dois é que existingObjectWithID:error:nunca retorna uma falha; ele sempre busca o objeto inteiro para você. Se você está tentando evitar isso (por exemplo, trabalhando com um objeto caro para buscar com uma grande propriedade de blob), precisa ser inteligente com objectWithID:ou objectRegisteredForID:, o que não gera falhas; ou use uma solicitação de busca configurada corretamente.]

rgeorge
fonte
11
-(NSManagedObject *)objectRegisteredForID:(NSManagedObjectID *)objectIDprovavelmente é útil quando você deseja apenas ver se um objeto já existe no contexto e não deseja buscá-lo.
Tony
Minha situação. No -tableView:didSelectRowAtIndexPath: UIAlertView com yes / no é exibido. Em "sim" - há algum trabalho com objeto. Eu uso NSFetchedResultsController+ atualizações em segundo plano CoreData do controle remoto. Portanto, não consigo armazenar objetos: enquanto o alerta estiver na tela, o armazenamento pode ser atualizado e o objeto removido. Eu guardo objectId e, em seguida, recupero-o novamente no delegado de alerta. Porque eu uso NSFetchedResultsController- todos os objetos necessários já estão em contexto neste momento. Além disso, quando não há objeto no contexto, o CoreData não deve fazer tentativas de busca inúteis.
kpower
boa resposta, obrigado! esses nomes de métodos são realmente complicados. é fácil de estragar tudo com a pessoa errada
chacal
Ótima resposta, obrigado pelo esclarecimento sobre objectWithId:- a necessidade de ligar insertObjectprimeiro para evitar um aumento de exceção na tentativa de disparar uma falha era realmente óbvia para mim.
Stanislav Pankevich
3
objectRegisteredForID:é útil quando você possui uma lista de objectIDs de uma operação em outro contexto e deseja atualizar apenas aqueles que podem ter dados obsoletos no contexto local. Isso mantém seu gráfico de objetos (e, portanto, o uso de memória) sob controle, e é melhor do que percorrer -registeredObjectse verificar os IDs dos objetos para ver se um objeto está com falha no seu contexto.
Sterling Archer
4

objectWithID:é o método que você está procurando e é a maneira recomendada de fazer isso. objectWithID:usará eficientemente o NSManagedObjectContext para extrair o objeto apenas quantos níveis forem necessários - ao contrário de outros meios para fazer isso. objectWithID:usará corretamente as informações da memória nos contextos pai, o coordenador de armazenamento persistente e o próprio armazenamento persistente antes de ir para o armazenamento de backup.

Isso é abordado em profundidade na sessão da WWDC 2012 "Melhores práticas de dados principais".

quellish
fonte