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?
Odpowiedzi:
Chcesz:
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:
... 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.... 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:
lubobjectRegisteredForID:
, które nie wywołują błędów; lub użyj odpowiednio skonfigurowanego żądania pobierania.]źródło
-(NSManagedObject *)objectRegisteredForID:(NSManagedObjectID *)objectID
jest prawdopodobnie przydatne, gdy chcesz tylko sprawdzić, czy obiekt już istnieje w kontekście i nie chcesz go pobierać.-tableView:didSelectRowAtIndexPath:
UIAlertView wyświetla się tak / nie. Na „tak” - jest jakaś praca z obiektem. UżywamNSFetchedResultsController
+ 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żywamNSFetchedResultsController
- 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.objectWithId:
- potrzeba zadzwonienia winsertObject
pierwszej kolejności, aby zapobiec zgłoszeniu wyjątku przy próbie odpalenia usterki, była dla mnie rzeczywiście nieoczywista.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-registeredObjects
i sprawdzanie identyfikatorów obiektów, aby sprawdzić, czy obiekt nie jest błędny w kontekście.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”.
źródło
Wersja Swift 5:
https://developer.apple.com/documentation/coredata/nsmanagedobjectcontext/1506686-existingobject
istnieją również metody
object(with:)
lubregisteredObject(for:)
. W zależności od tego, czego potrzebujesz.źródło