Apa yang harus saya lakukan agar Data Inti memigrasi model secara otomatis?

96

Saya telah membaca dokumentasi tentang migrasi otomatis / ringan untuk model Data Inti - tetapi saya mengalami masalah dalam menerapkannya.

Seperti yang saya pahami, aplikasi harus memperhatikan bahwa model yang dimilikinya dan model yang ada di perangkat sudah tidak sama. Jika Anda hanya menambahkan atribut atau hubungan dan perubahan sederhana yang serupa maka model harus diupgrade secara otomatis.

Ada petunjuk - apakah saya perlu mengatur sesuatu di Xcode?

Grouchal
sumber

Jawaban:

138

Sekarang saya telah mengetahui bahwa ini cukup sederhana - setelah Anda tahu di mana mencarinya.

Di AppDelegate saya, saya menyiapkan NSPersistentStoreCoordinator - dan Anda perlu menambahkan beberapa opsi ke sini untuk memberitahunya untuk menangani migrasi otomatis:

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:

[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,

[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

NSError *error;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];

if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
    // Handle error
    NSLog(@"Problem with PersistentStoreCoordinator: %@",error);
}

Maka Anda perlu melakukan sedikit trik di xCode:

  1. Pilih file xcdatamodel Anda
  2. Pilih Menu Desain di bagian atas - lalu Model Data - lalu pilih Tambahkan Versi Model
  3. File xcdatamodel Anda kemudian akan dipindahkan ke direktori baru dengan nama yang sama dengan file xcdatamodel Anda tetapi dengan ekstensi xcdatamodeld - akan ada file kedua di direktori ini dengan 2 di namanya. Pilih file baru dan kemudian Desain-> Model Data-> Atur Versi Saat Ini ( di Xcode 4 Anda melakukan ini )
  4. Jika Anda telah membuat perubahan yang menyebabkan proyek Anda tidak kompatibel - hapus perubahan ini dari file xcdatamodel asli. Jika Anda belum membuat perubahan - edit saja file 2.xcdatamodel (yang baru saja Anda buat versi sekarang).
  5. Sekarang ketika Anda menginstal versi ini ke perangkat yang memiliki model lama - itu akan secara otomatis meningkatkan model itu ke model baru.

Ini tampak hebat dan sesederhana yang saya inginkan - tetapi saya pikir Anda perlu berhati-hati selama pengembangan saat Anda mengubah model - jika tidak, Anda harus membuat versi baru untuk setiap perubahan.

Saya pikir apa yang akan saya lakukan adalah saya akan menyimpan semua file yang diubah dan kemudian setelah saya siap untuk menerapkan pembaruan saya, saya akan menghapus semua file di antara dan hanya menerapkan dengan model terlama dan terbaru.


PEMBARUAN (15/07/2011):

Terima kasih kepada @ rockstarberlin karena menunjukkan ada dokumentasi terbaru di apple:

Xcode 4: Menyetel Versi Terkelola Model Objek Terkelola

Perbarui: 8/19/2013 tautan yang lebih baik:

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmModelFormat.html

Grouchal
sumber
Saya sarankan untuk membaca Panduan Pemindahan dan Pembuatan Versi Data Inti, tersedia di penampil dokumen Xcode dan di developer.apple.com.
Hunter
1
Saya tidak menemukan jawabannya di sana secara sederhana - butuh beberapa saat untuk mengetahui bagaimana melakukan ini.
Grouchal
NSInferMappingModelAutomaticallyOption berfungsi dengan baik, tetapi hanya untuk pemetaan sederhana, seperti mengubah nama atribut. Untuk sesuatu yang lebih rumit (hubungan, menghapus atau menambahkan entitas), Anda perlu menambahkan model pemetaan. Jika Xcode mengeluh bahwa NSInferMappingModelAutomaticallyOption tidak dideklarasikan, tambahkan #import <CoreData / CoreData.h> ke file header delegasi aplikasi Anda.
Elise van Looij
Saya menambahkan beberapa entitas ke model saya dan mendapatkan kesalahan "Model yang digunakan untuk membuka toko tidak kompatibel dengan yang digunakan untuk membuat toko". Solusi Anda memperbaikinya! Terima kasih banyak!
Karsten Silz
1
Lihat jawaban Santthosh di bawah ini jika Anda mendapatkan kesalahan "tidak dapat menggabungkan model dengan dua entitas berbeda bernama" setelah mengikuti petunjuk ini.
benvolioT
14

Ini sangat membantu. Dokumentasi Apple - seperti biasa - sangat tidak lengkap. Saya sarankan melakukan build bersih, karena saya mengalami error "Tidak dapat menggabungkan model dengan dua entitas berbeda xxx" saat pertama kali menjalankan setelah melakukan perubahan ini. Bangunan yang bersih memperbaikinya.

Scott Berarti
sumber
Bangunan yang bersih juga memperbaiki masalah saya.
jrainbow
6

Jawaban Grouchal sempurna ... tetapi jika Anda masih memiliki pesan "Tidak dapat menggabungkan model dengan dua entitas yang berbeda xxx" bahkan setelah membersihkan build beberapa kali ... Anda mungkin mengalami masalah dengan cara managedObjectModel dimuat .. . lihat yang satu ini ... yang membantuku memperbaikinya ..

masalah migrasi data inti

Santthosh
sumber
3

Juga, jika Anda menemukan posting ini, seperti yang saya lakukan, setelah mendapatkan kesalahan "Model yang digunakan untuk membuka toko tidak kompatibel dengan yang digunakan untuk membuat toko" dan Anda hanya men-debug menggunakan simulator dan ingin sepenuhnya mengganti menginstal model lama, Anda dapat mengatur ulang aplikasi Simulator atau menghapus aplikasi Anda dari simulator mungkin juga akan berfungsi.

Tidak terpikir oleh saya untuk mencoba ini sampai membaca posting di sini, di mana saya menyadari bahwa saya telah menginstal aplikasi di simulator dan kemudian mengubah model, menyebabkan kesalahan run-time yang disebutkan di atas.

dreyln
sumber
1

Untuk menindaklanjuti jawaban Santthosh, kupikir aku akan memposting potongan kode di sini sebagai gantinya. Anda perlu membuat managedObjectModel dengan initWithContentsOfURL:alih - alih mergedModelFromBundles:jika tidak, Anda akan mendapatkan kesalahan:

Tidak dapat menggabungkan model dengan dua entitas yang berbeda XXX dan XXX

Jika file Model Anda bernama "Model", berikut ini cara Anda membuat managedObjectModel:

NSString *path = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL]; 

Penghargaan untuk posting blog ini .

samvermette
sumber
1

menu di Xcode 4 berubah sedikit. di sini adalah penjelasan bagaimana melakukannya di Xcode 4:

Xcode 4: Menyetel Versi Terkelola Model Objek Terkelola

rockstarberlin
sumber
Tautan sudah rusak. Tautan ke dokumentasi Apple berlangsung sekitar dua bulan :(
mxcl
1

Saya telah mengalami masalah ini selama bertahun-tahun, dan saya mencoba semua jawaban ini tetapi tidak berhasil. Hari ini saya akhirnya menemukan apa yang saya lakukan salah. Masalah yang sangat sederhana, tapi saya mengabaikannya. Saat membuat versi model data yang lebih baru, jika Anda MENAMBAHKAN kolom, pastikan untuk menandainya sebagai OPSIONAL. Jika Anda tidak, migrasi sederhana tidak akan berfungsi karena nilai kolom baru tidak akan diisi.

Segera setelah saya memastikan kolom baru saya memiliki centang "opsional", saya mencoba migrasi lagi dan berhasil.

Brain2000
sumber
1

Saya tersandung ke posting ini karena masalah yang berbeda, tetapi kesalahannya adalah " Konfigurasi model yang digunakan untuk membuka toko tidak sesuai dengan yang digunakan untuk membuat toko. "

Inilah masalah saya dan solusi untuk itu. Dalam model saya, saya menggunakan konfigurasi . Saya memiliki beberapa entitas yang disimpan dalam satu file dan yang lainnya di file kedua. (Saya memiliki beberapa default yang mungkin perlu diunduh secara berkala, dan akan sangat merepotkan untuk menggabungkannya menjadi keseluruhan). Bagaimanapun, saya membuat entitas baru. Programnya sepertinya berjalan dengan baik, tetapi setiap kali saya keluar, saya mendapatkan kesalahan di atas.

Solusinya adalah melihat konfigurasi saya, menyadari bahwa saya memiliki entitas yang saat ini tidak ada dalam konfigurasi apa pun, dan menambahkannya ke salah satu. Berjalan seperti mimpi.

Ini tidak akan memperbaiki masalah OP. Tetapi mungkin beberapa orang yang frustrasi yang mendarat di sini melalui google akan berada di perahu yang saya tumpangi :)

Cappy
sumber
0

iOS 4.0+

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"model" withExtension:@"momd"];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
Stian Høiland
sumber
0

Pengeditan kecil untuk instruksi mengagumkan @ Grouchal di atas untuk Xcode versi 5:

Lama: 2. Pilih Menu Desain di bagian atas - lalu Model Data - lalu pilih Tambahkan Versi Model

Versi 5+: 2. Pilih menu Editor, lalu Tambahkan Versi Model…, ketikkan nama Versi Anda dan Berdasarkan model (pilih model asli Anda dari daftar)

PGSeattle
sumber