Bagaimana cara mendapatkan objek Data Inti dari ID Objek tertentu?

120

Saya bisa dengan mudah mendapatkan ID objek di Core Data menggunakan kode berikut:

NSManagedObjectID *moID = [managedObject objectID];

Namun, adakah cara untuk mengeluarkan objek dari penyimpanan data inti dengan memberinya ID objek tertentu? Saya tahu bahwa saya dapat melakukan ini dengan menggunakan NSFetchRequest, seperti ini:

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

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

Namun, saya ingin melakukannya dengan cara yang tidak memulai permintaan pengambilannya sendiri. Ada ide?

Jason
sumber
Tetapi dengan cara permintaan pengambilan Anda dapat menyetel properti atau relasi untuk diambil sebelumnya yang akan memberi Anda efisiensi yang sangat baik daripada lebih banyak kueri saat Anda mengakses sesuatu.
malhal

Jawaban:

208

Kamu ingin:

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

Mengambil objek dari penyimpanan yang memiliki ID tersebut, atau nihil jika tidak ada.

(Perhatikan: ada dua metode di NSManagedObjectContext dengan nama yang tampak serupa yang membuat saya tersandung. Untuk membantu menjaganya tetap lurus, inilah yang dilakukan dua metode lainnya:

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

... akan membuat objek kesalahan dengan objectID yang disediakan, apakah objek tersebut benar-benar ada di toko atau tidak. Jika tidak ada, apa pun yang mengaktifkan kesalahan akan gagal kecuali Anda memasukkan objek terlebih dahulu dengan NSManagedObjectContext's insertObject:. Satu-satunya kegunaan yang saya temukan untuk ini adalah menyalin objek dari toko ke toko sambil mempertahankan ObjectID.

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

... akan mengembalikan objek yang memiliki ID tersebut, jika telah diambil dari penyimpanan oleh managedObjectContext ini. Jika ada yang tahu untuk apa metode ini berguna, silakan beri komentar.)

[eta .: Perbedaan penting lainnya antara metode pertama dan dua metode lainnya adalah existingObjectWithID:error:tidak pernah mengembalikan kesalahan; itu selalu mengambil seluruh objek untuk Anda. Jika Anda mencoba menghindarinya (misalnya bekerja dengan objek yang mahal untuk diambil dengan properti gumpalan besar), Anda harus pandai dengan objectWithID:atau objectRegisteredForID:, yang tidak menembakkan kesalahan; atau gunakan permintaan pengambilan yang dikonfigurasi dengan benar.]

rgeorge
sumber
11
-(NSManagedObject *)objectRegisteredForID:(NSManagedObjectID *)objectIDmungkin berguna saat Anda hanya ingin melihat apakah suatu objek sudah ada dalam konteks dan tidak ingin mengambilnya.
Tony
Situasi saya. Di -tableView:didSelectRowAtIndexPath: UIAlertView dengan yes / no ditampilkan. Pada "ya" - ada beberapa pekerjaan dengan objek. Saya menggunakan NSFetchedResultsController+ latar belakang pembaruan CoreData dari jarak jauh. Jadi saya tidak bisa menyimpan objek: saat peringatan ada di layar, penyimpanan bisa diperbarui dan objek dihapus. Saya menyimpan objectId, lalu mengambilnya sekali lagi di delegasi peringatan. Karena saya menggunakan NSFetchedResultsController- semua objek yang diperlukan sudah ada dalam konteks saat ini. Selain itu, jika tidak ada objek dalam konteks, CoreData seharusnya tidak melakukan upaya pengambilan yang tidak berguna.
kpower
jawaban yang bagus, terima kasih! nama metode ini sangat rumit. mudah untuk mengacaukan semuanya dengan yang salah
jackal
Jawaban yang bagus, terima kasih atas klarifikasi tentang objectWithId:- kebutuhan menelepon insertObjectterlebih dahulu untuk mencegah kenaikan pengecualian pada upaya untuk melakukan kesalahan memang tidak saya sadari.
Stanislav Pankevich
3
objectRegisteredForID:berguna ketika Anda memiliki daftar objectID dari operasi dalam konteks lain, dan Anda hanya ingin memperbarui yang mungkin memiliki data usang dalam konteks lokal. Ini membuat grafik objek Anda (dan karena itu penggunaan memori) tetap terkendali, dan itu lebih baik daripada mengulang -registeredObjectsdan memeriksa objectIDs untuk melihat apakah sebuah objek disalahkan untuk konteks Anda.
Sterling Archer
4

objectWithID:adalah metode yang Anda cari, dan ini adalah cara yang disarankan untuk melakukannya. objectWithID:akan secara efisien menggunakan NSManagedObjectContext untuk menarik objek hanya sebanyak level yang diperlukan - tidak seperti beberapa cara lain untuk melakukan ini. objectWithID:akan menggunakan informasi dalam memori dengan benar dalam konteks induk, koordinator penyimpanan persisten, dan penyimpanan persisten itu sendiri sebelum pergi ke penyimpanan pendukung.

Ini dibahas secara mendalam di sesi WWDC 2012 "Praktik Terbaik Data Inti".

memadamkan
sumber