Saya perlu membuat NSManagedObject
instance, melakukan beberapa hal dengannya, lalu membuangnya atau menyimpannya ke sqlite db. Masalahnya adalah, saya tidak dapat membuat contoh NSManagedObject
unconnected to NSManagedObjectContext
dan ini berarti saya harus membersihkan entah bagaimana setelah saya memutuskan bahwa saya tidak memerlukan beberapa objek di db saya.
Untuk mengatasinya, saya telah membuat penyimpanan dalam memori menggunakan koordinator yang sama dan saya menempatkan objek sementara di sana dengan menggunakan assignObject:toPersistentStore.
Sekarang, bagaimana cara memastikan bahwa objek sementara ini tidak mendapatkan data, yang saya ambil dari umum untuk konteks kedua toko? Atau apakah saya harus membuat konteks terpisah untuk tugas semacam itu?
UPD:
Sekarang saya berpikir tentang membuat konteks terpisah untuk penyimpanan dalam memori. Bagaimana cara memindahkan objek dari satu konteks ke konteks lainnya? Hanya menggunakan [konteks insertObject:]? Apakah akan berfungsi dengan baik dalam penyiapan ini? Jika saya memasukkan satu objek dari grafik objek, apakah seluruh grafik juga dimasukkan ke dalam konteks?
sumber
Jawaban:
CATATAN: Jawaban ini sangat tua. Lihat komentar untuk sejarah lengkap. Rekomendasi saya telah berubah dan saya tidak lagi merekomendasikan penggunaan
NSManagedObject
instans yang tidak terkait . Rekomendasi saya saat ini adalah menggunakanNSManagedObjectContext
instance anak sementara .Jawaban Asli
Cara termudah untuk melakukannya adalah dengan membuat
NSManagedObject
instance Anda tanpa yang terkaitNSManagedObjectContext
.NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:myMOC]; NSManagedObject *unassociatedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
Kemudian saat Anda ingin menyimpannya:
[myMOC insertObject:unassociatedObject]; NSError *error = nil; if (![myMoc save:&error]) { //Respond to the error }
sumber
iOS5 memberikan alternatif yang lebih sederhana untuk jawaban Mike Weller. Sebaliknya, gunakan anak NSManagedObjectContext. Ini menghilangkan kebutuhan untuk trampolin melalui NSNotificationCenter
Untuk membuat konteks anak:
NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; childContext.parentContext = myMangedObjectContext;
Kemudian buat objek Anda menggunakan konteks anak:
NSManagedObject *o = [NSEntityDescription insertNewObjectForEntityForName:@"MyObject" inManagedObjectContext:childContext];
Perubahan hanya diterapkan ketika konteks anak disimpan. Jadi untuk membuang perubahan jangan simpan.
Masih ada batasan pada hubungan. yaitu Anda tidak dapat membuat hubungan dengan objek dalam konteks lain. Untuk menyiasati penggunaan objectID ini, untuk mendapatkan objek dari konteks anak. misalnya.
NSManagedObjectID *mid = [myManagedObject objectID]; MyManagedObject *mySafeManagedObject = [childContext objectWithID:mid]; object.relationship=mySafeManagedObject;
Catatan, menyimpan konteks anak menerapkan perubahan ke konteks induk. Menyimpan konteks induk mempertahankan perubahan.
Lihat wwdc 2012 sesi 214 untuk penjelasan lengkapnya.
sumber
moc
di cuplikan ketiga? Apakah ituchildContext
ataumyMangedObjectContext
?NSManagedObject
sudah menyediakan yang relevanNSManagedObjectContext
, Anda dapat mengotomatiskan pilihan konteks:NSManagedObject* objectRelatedContextually = [objectWithRelationship.managedObjectContext objectWithID:objectRelated.objectID];
dan kemudianobjectWithRelationship.relationship = objectRelatedContextually;
.Cara yang benar untuk mencapai hal semacam ini adalah dengan konteks objek terkelola yang baru. Anda membuat konteks objek terkelola dengan penyimpanan persisten yang sama:
NSManagedObjectContext *tempContext = [[[NSManagedObjectContext alloc] init] autorelease]; [tempContext setPersistentStore:[originalContext persistentStore]];
Kemudian Anda menambahkan objek baru, mengubahnya, dll.
Saat tiba waktunya untuk menyimpan, Anda perlu memanggil [tempContext save: ...] di tempContext, dan menangani notifikasi penyimpanan untuk menggabungkannya ke dalam konteks asli Anda. Untuk membuang objek, cukup lepaskan konteks sementara ini dan lupakan.
Jadi, saat Anda menyimpan konteks sementara, perubahan tersebut tetap ada di penyimpanan, dan Anda hanya perlu mengembalikan perubahan itu ke konteks utama Anda:
/* Called when the temp context is saved */ - (void)tempContextSaved:(NSNotification *)notification { /* Merge the changes into the original managed object context */ [originalContext mergeChangesFromContextDidSaveNotification:notification]; } // Here's where we do the save itself // Add the notification handler [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tempContextSaved:) name:NSManagedObjectContextDidSaveNotification object:tempContext]; // Save [tempContext save:NULL]; // Remove the handler again [[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:tempContext];
Ini juga merupakan cara Anda menangani operasi data inti multi-utas. Satu konteks per utas.
Jika Anda perlu mengakses objek yang ada dari konteks sementara ini (untuk menambahkan relasi, dll.), Anda perlu menggunakan ID objek untuk mendapatkan instance baru seperti ini:
NSManagedObject *objectInOriginalContext = ...; NSManagedObject *objectInTemporaryContext = [tempContext objectWithID:[objectInOriginalContext objectID]];
Jika Anda mencoba menggunakan an
NSManagedObject
dalam konteks yang salah, Anda akan mendapatkan pengecualian saat menyimpan.sumber
NSManagedObjectContext
mahal di memori dan CPU. Saya menyadari ini awalnya di beberapa contoh Apple, tetapi mereka telah memperbarui dan memperbaiki contoh tersebut.Membuat objek sementara dari konteks nil berfungsi dengan baik sampai Anda benar-benar mencoba untuk memiliki hubungan dengan objek yang konteksnya! = Nil!
pastikan Anda setuju dengan itu.
sumber
Apa yang Anda gambarkan sebenarnya untuk apa
NSManagedObjectContext
.Dari Panduan Pemrograman Data Inti: Dasar Data Inti
Dan Panduan Pemrograman Data Inti: Validasi Objek Terkelola
NSManagedObjectContext
s dirancang agar ringan. Anda dapat membuat dan membuangnya sesuka hati - itu adalah koordinator penyimpanan yang gigih dan ketergantungannya yang "berat". Seorang koordinator toko persisten dapat memiliki banyak konteks yang terkait dengannya. Di bawah model kurungan utas yang lebih lama dan usang, ini berarti menyetel koordinator penyimpanan persisten yang sama pada setiap konteks. Hari ini berarti menghubungkan konteks bertingkat ke konteks akar yang terkait dengan koordinator penyimpanan persisten.Buat konteks, buat dan modifikasi objek terkelola dalam konteks itu. Jika Anda ingin mempertahankannya dan mengomunikasikan perubahan itu, simpan konteksnya. Jika tidak, buang.
Mencoba membuat objek terkelola secara independen akan menimbulkan
NSManagedObjectContext
masalah. Ingatlah bahwa Data Inti pada akhirnya adalah mekanisme pelacakan perubahan untuk grafik objek. Karena itu, objek yang dikelola benar-benar merupakan bagian dari konteks objek yang dikelola . Konteks mengamati siklus hidup mereka , dan tanpa konteks tidak semua fungsionalitas objek yang dikelola akan bekerja dengan benar.sumber
Bergantung pada penggunaan Anda atas objek sementara, ada beberapa peringatan untuk rekomendasi di atas. Kasus penggunaan saya adalah saya ingin membuat objek sementara dan mengikatnya ke tampilan. Ketika pengguna memilih untuk menyimpan objek ini, saya ingin mengatur hubungan ke objek yang ada dan menyimpannya. Saya ingin melakukan ini untuk menghindari membuat objek sementara untuk menampung nilai-nilai itu. (Ya, saya bisa menunggu sampai pengguna menyimpan dan kemudian mengambil konten tampilan tetapi saya meletakkan tampilan ini di dalam tabel dan logika untuk melakukan ini kurang elegan.)
Opsi untuk objek sementara adalah:
1) (Lebih disukai) Buat objek sementara dalam konteks anak. Ini tidak akan berfungsi karena saya mengikat objek ke UI dan saya tidak dapat menjamin pengakses objek dipanggil pada konteks anak. (Saya tidak menemukan dokumentasi yang menyatakan sebaliknya, jadi saya harus berasumsi.)
2) Buat objek sementara dengan konteks objek nihil. Ini tidak berfungsi dan mengakibatkan kehilangan / kerusakan data.
Solusi Saya: Saya menyelesaikan ini dengan membuat objek sementara dengan konteks objek nihil tetapi ketika saya menyimpan objek, daripada memasukkannya sebagai # 2, saya menyalin semua atributnya ke dalam objek baru yang saya buat dalam konteks utama. Saya membuat metode pendukung dalam subkelas NSManagedObject saya yang disebut cloneInto: yang memungkinkan saya menyalin atribut dan hubungan dengan mudah untuk objek apa pun.
sumber
Bagi saya, jawaban Marcus tidak berhasil. Inilah yang berhasil untuk saya:
NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:myMOC]; NSManagedObject *unassociatedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
kemudian, jika saya memutuskan untuk menyimpannya:
[myMOC insertObject:unassociatedObjet]; NSError *error = nil; [myMoc save:&error]; //Check the error!
Kita juga tidak boleh lupa untuk melepaskannya
sumber
Saya menulis ulang jawaban ini untuk Swift karena semua pertanyaan serupa untuk segera dialihkan ke pertanyaan ini.
Anda dapat mendeklarasikan objek tanpa ManagedContext menggunakan kode berikut.
let entity = NSEntityDescription.entity(forEntityName: "EntityName", in: myContext) let unassociatedObject = NSManagedObject.init(entity: entity!, insertInto: nil)
Nanti, untuk menyimpan objek, Anda dapat memasukkannya ke dalam konteks dan menyimpannya.
myContext.insert(unassociatedObject) // Saving the object do { try self.stack.saveContext() } catch { print("save unsuccessful") } }
sumber