Comment obtenir un objet Core Data à partir d'un ID d'objet spécifique?

120

Je peux facilement obtenir l'ID d'un objet dans Core Data en utilisant le code suivant:

NSManagedObjectID *moID = [managedObject objectID];

Cependant, existe-t-il un moyen de sortir un objet du magasin de données de base en lui attribuant un ID d'objet spécifique? Je sais que je peux le faire en utilisant un NSFetchRequest, comme ceci:

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

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

Cependant, j'aimerais le faire d'une manière qui ne lance pas sa propre demande de récupération. Des idées?

Jason
la source
Mais avec la méthode de demande de récupération, vous pouvez définir des propriétés ou des relations à pré-extraire, ce qui vous donnera une excellente efficacité plutôt que beaucoup plus de requêtes lorsque vous accédez aux choses.
malhal

Réponses:

208

Tu veux:

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

Récupère l'objet du magasin qui a cet ID, ou nul s'il n'existe pas.

(Attention: il existe deux méthodes sur NSManagedObjectContext avec des noms d'apparence similaire qui m'ont fait trébucher. Pour les aider à rester dans l'ordre, voici ce que font les deux autres:

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

... créera un objet fault avec l'ID d'objet fourni, qu'un tel objet existe ou non dans le magasin. S'il n'existe pas, tout ce qui déclenche l'erreur échouera sauf si vous insérez d'abord l'objet avec NSManagedObjectContext insertObject:. La seule utilisation que j'ai trouvée pour cela est de copier des objets d'un magasin à un autre tout en préservant les ObjectID.

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

... renverra l'objet qui a cet ID, s'il a été extrait du magasin par ce managedObjectContext. Si quelqu'un sait à quoi cette méthode est utile, veuillez commenter.)

[eta.: Une autre différence importante entre la première méthode et les deux autres est qu'elle existingObjectWithID:error:ne renvoie jamais de faute; il récupère toujours l'objet entier pour vous. Si vous essayez d'éviter cela (par exemple, travailler avec un objet coûteux à récupérer avec une grande propriété blob), vous devez être intelligent avec objectWithID:ou objectRegisteredForID:, qui ne déclenche pas les défauts; ou utilisez une demande de récupération correctement configurée.]

rgeorge
la source
11
-(NSManagedObject *)objectRegisteredForID:(NSManagedObjectID *)objectIDest probablement utile lorsque vous voulez juste voir si un objet existe déjà dans le contexte et que vous ne voulez pas le récupérer.
Tony
Ma situation. Sur -tableView:didSelectRowAtIndexPath: UIAlertView avec oui / non s'affiche. Sur "oui" - il y a du travail avec l'objet. J'utilise NSFetchedResultsController+ les mises à jour CoreData de fond à distance. Je ne peux donc pas stocker d'objet: tant que l'alerte est à l'écran, le stockage peut être mis à jour et l'objet supprimé. Je stocke objectId, puis le récupère une fois de plus dans le délégué d'alerte. Parce que j'utilise NSFetchedResultsController- tous les objets nécessaires sont déjà dans leur contexte à ce moment. De plus, quand il n'y a pas d'objet dans le contexte, CoreData ne devrait pas rendre la récupération inutile.
kpower
belle réponse, merci! ces noms de méthodes sont vraiment délicats. il est facile de tout gâcher avec le mauvais
chacal
Excellente réponse, merci pour la clarification objectWithId:- la nécessité d'appeler d' insertObjectabord pour éviter une augmentation d'exception lors d'une tentative de déclenchement d'une faute n'était en effet pas évidente pour moi.
Stanislav Pankevich
3
objectRegisteredForID:est utile lorsque vous avez une liste des objectID d'une opération dans un autre contexte et que vous souhaitez uniquement mettre à jour ceux qui peuvent avoir des données périmées dans le contexte local. Cela permet de garder votre graphique d'objets (et donc l'utilisation de la mémoire) sous contrôle, et c'est mieux que de parcourir -registeredObjectset de vérifier les objectID pour voir si un objet est défectueux pour votre contexte.
Sterling Archer
4

objectWithID:est la méthode que vous recherchez, et c'est la méthode recommandée pour ce faire. objectWithID:utilisera efficacement NSManagedObjectContext pour extraire l'objet uniquement autant de niveaux que nécessaire - contrairement à certains des autres moyens de le faire. objectWithID:utilisera correctement les informations en mémoire dans les contextes parents, le coordinateur de magasin persistant et le magasin persistant lui-même avant d'aller au stockage de sauvegarde.

Cette question est traitée en détail dans la session 2012 de la WWDC «Meilleures pratiques en matière de données de base».

apaiser
la source