Как получить объект Core Data из определенного идентификатора объекта?

120

Я могу легко получить идентификатор объекта в Core Data, используя следующий код:

NSManagedObjectID *moID = [managedObject objectID];

Однако есть ли способ получить объект из основного хранилища данных, присвоив ему конкретный идентификатор объекта? Я знаю, что могу сделать это с помощью NSFetchRequest, например:

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

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

Однако я бы хотел сделать это таким образом, чтобы не инициировать собственный запрос на выборку. Любые идеи?

Джейсон
источник
Но с помощью способа запроса выборки вы можете установить свойства или отношения, которые будут предварительно извлечены, что даст вам отличную эффективность, а не множество других запросов при доступе к вещам.
Malhal

Ответы:

208

Вы хотите:

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

Выбирает объект из магазина с этим идентификатором или nil, если он не существует.

(Имейте в виду: есть два метода в NSManagedObjectContext с похожими именами, которые меня сбили с толку. Чтобы помочь им понять, вот что делают два других:

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

... создаст объект ошибки с предоставленным идентификатором объекта, независимо от того , существует ли такой объект в хранилище или нет. Если его не существует, все, что вызывает ошибку, завершится ошибкой, если вы сначала не вставите объект с помощью NSManagedObjectContext insertObject:. Единственное использование, которое я нашел для этого, - это копирование объектов из магазина в хранилище с сохранением ObjectID.

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

... вернет объект с этим идентификатором, если он был получен из хранилища этим managedObjectContext. Если кто знает, чем полезен этот метод, прокомментируйте.)

[eta .: Еще одно важное отличие первого метода от двух других заключается в том, что он existingObjectWithID:error:никогда не возвращает ошибку; он всегда получает за вас весь объект. Если вы пытаетесь этого избежать (например, работая с дорогостоящим для извлечения объектом с большим свойством blob), вы должны быть умны с objectWithID:или objectRegisteredForID:, которые не вызывают ошибок; или используйте правильно настроенный запрос на выборку.]

rgeorge
источник
11
-(NSManagedObject *)objectRegisteredForID:(NSManagedObjectID *)objectIDвероятно, полезно, когда вы просто хотите увидеть, существует ли уже объект в контексте, и не хотите его получать.
Тони
Моя ситуация. На -tableView:didSelectRowAtIndexPath: UIAlertView отображается да / нет. На «да» - есть работа с объектом. Я использую NSFetchedResultsController+ фоновые обновления CoreData удаленно. Поэтому я не могу сохранить объект: пока на экране отображается предупреждение, хранилище можно обновить, а объект удалить. Я сохраняю objectId, а затем снова получаю его в делегате предупреждения. Потому что использую NSFetchedResultsController- все необходимые объекты к этому моменту уже находятся в контексте. Более того, когда в контексте нет объекта, CoreData не должен делать бесполезные попытки выборки.
kpower
хороший ответ, спасибо! эти имена методов действительно хитрые. легко все испортить с неправильным
jackal
Отличный ответ, спасибо за пояснение objectWithId:- необходимость insertObjectсначала позвонить, чтобы предотвратить возникновение исключения при попытке запустить ошибку, действительно была для меня неочевидной.
Станислав Панкевич
3
objectRegisteredForID:полезно, когда у вас есть список идентификаторов объектов из операции в другом контексте, и вы хотите обновить только те, которые могут иметь устаревшие данные в локальном контексте. Это контролирует ваш граф объектов (и, следовательно, использование памяти), и это лучше, чем перебирать -registeredObjectsи проверять идентификаторы объектов, чтобы увидеть, не поврежден ли объект для вашего контекста.
Стерлинг Арчер
4

objectWithID:- это метод, который вы ищете, и это рекомендуемый способ. objectWithID:будет эффективно использовать NSManagedObjectContext для извлечения объекта только на столько уровней, сколько необходимо - в отличие от некоторых других средств для этого. objectWithID:будет правильно использовать информацию в памяти в родительских контекстах, координаторе постоянного хранилища и самом постоянном хранилище перед переходом в резервное хранилище.

Это подробно рассматривается в сеансе WWDC 2012 «Лучшие практики работы с основными данными».

quellish
источник