Jak uzyskać obiekt danych podstawowych z określonego identyfikatora obiektu?

120

Mogę łatwo uzyskać identyfikator obiektu w danych podstawowych za pomocą następującego kodu:

NSManagedObjectID *moID = [managedObject objectID];

Czy jednak istnieje sposób, aby wydobyć obiekt z podstawowego magazynu danych, nadając mu określony identyfikator obiektu? Wiem, że mogę to zrobić za pomocą NSFetchRequest, na przykład:

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

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

Chciałbym jednak zrobić to w sposób, który nie inicjuje własnego żądania pobierania. Jakieś pomysły?

Jason
źródło
Ale dzięki żądaniu pobierania można ustawić właściwości lub relacje, które mają być wstępnie pobrane, co zapewni doskonałą wydajność, a nie wiele więcej zapytań podczas uzyskiwania dostępu do rzeczy.
malhal

Odpowiedzi:

208

Chcesz:

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

Pobiera obiekt ze sklepu, który ma ten identyfikator, lub nil, jeśli nie istnieje.

(Uwaga: w NSManagedObjectContext są dwie metody o podobnych pozornych nazwach, które mnie zaskoczyły. Aby zachować prostotę, oto co robią pozostałe dwie:

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

... utworzy obiekt błędu z podanym objectID, niezależnie od tego , czy taki obiekt rzeczywiście istnieje w magazynie. Jeśli nie istnieje, wszystko, co wyzwala błąd, zakończy się niepowodzeniem, chyba że najpierw wstawisz obiekt z NSManagedObjectContext's insertObject:. Jedynym zastosowaniem, jakie znalazłem, jest kopiowanie obiektów ze sklepu do magazynu przy zachowaniu ObjectID.

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

... zwróci obiekt, który ma ten identyfikator, jeśli został pobrany ze sklepu przez ten managedObjectContext. Jeśli ktoś wie, do czego ta metoda jest przydatna, proszę o komentarz.)

[eta .: Inną ważną różnicą między pierwszą metodą a pozostałymi dwoma jest to, że existingObjectWithID:error:nigdy nie zwraca błędu; zawsze pobiera dla ciebie cały obiekt. Jeśli próbujesz tego uniknąć (np. Pracujesz z obiektem drogim do pobrania z właściwością dużego blobu), musisz sprytnie posługiwać się objectWithID:lub objectRegisteredForID:, które nie wywołują błędów; lub użyj odpowiednio skonfigurowanego żądania pobierania.]

rgeorge
źródło
11
-(NSManagedObject *)objectRegisteredForID:(NSManagedObjectID *)objectIDjest prawdopodobnie przydatne, gdy chcesz tylko sprawdzić, czy obiekt już istnieje w kontekście i nie chcesz go pobierać.
Tony
Moja sytuacja. Na -tableView:didSelectRowAtIndexPath: UIAlertView wyświetla się tak / nie. Na „tak” - jest jakaś praca z obiektem. Używam NSFetchedResultsController+ aktualizacje tło CoreData od zdalnego. Więc nie mogę przechowywać obiektu: gdy na ekranie jest alert, można zaktualizować pamięć i usunąć obiekt. Przechowuję objectId, a następnie pobieram go jeszcze raz w alercie delegata. Ponieważ używam NSFetchedResultsController- wszystkie potrzebne obiekty są już w tej chwili w kontekście. Co więcej, gdy nie ma obiektu w kontekście, CoreData nie powinien wykonywać bezużytecznych prób pobierania.
kpower
dobra odpowiedź, dziękuję! te nazwy metod są naprawdę trudne. łatwo wszystko zepsuć niewłaściwym
szakalem
Świetna odpowiedź, dzięki za wyjaśnienie objectWithId:- potrzeba zadzwonienia w insertObjectpierwszej kolejności, aby zapobiec zgłoszeniu wyjątku przy próbie odpalenia usterki, była dla mnie rzeczywiście nieoczywista.
Stanislav Pankevich
3
objectRegisteredForID:przydaje się, gdy masz listę identyfikatorów obiektów z operacji w innym kontekście i chcesz zaktualizować tylko te, które mogą mieć nieaktualne dane w kontekście lokalnym. Dzięki temu wykres obiektu (a tym samym zużycie pamięci) pozostaje pod kontrolą i jest to lepsze niż przechodzenie w pętli -registeredObjectsi sprawdzanie identyfikatorów obiektów, aby sprawdzić, czy obiekt nie jest błędny w kontekście.
Sterling Archer
4

objectWithID:jest metodą, której szukasz i jest to zalecany sposób. objectWithID:efektywnie użyje NSManagedObjectContext do ściągnięcia obiektu tylko na tyle poziomów, ile potrzeba - w przeciwieństwie do niektórych innych sposobów robienia tego. objectWithID:będzie poprawnie używać informacji z pamięci w kontekstach nadrzędnych, koordynatorze magazynu trwałego i samego magazynu trwałego przed przejściem do magazynu zapasowego.

Jest to szczegółowo omówione w sesji WWDC 2012 „Najlepsze praktyki w zakresie danych podstawowych”.

quellish
źródło