Apple'ın belgelerinde neyi ima ettiğini buldum . Aslında çok kolay ama bariz olmadan önce gidilmesi gereken uzun bir yol. Açıklamayı bir örnekle açıklayacağım. İlk durum şudur:
Veri Modeli Sürümü 1
"Çekirdek veri depolamaya sahip navigasyon tabanlı uygulama" şablonuyla bir proje oluşturduğunuzda elde ettiğiniz modeldir. Bunu derledim ve hepsi farklı değerlere sahip yaklaşık 2k giriş oluşturmak için bir for döngüsü yardımıyla bazı sert vuruşlar yaptım. NSDate değerine sahip 2.000 etkinliğe gidiyoruz.
Şimdi veri modelinin şuna benzeyen ikinci bir sürümünü ekliyoruz:
Veri Modeli Versiyon 2
Aradaki fark şudur: Event varlığı gitti ve bizim iki yenimiz var. Bir zaman damgasını a olarak saklayan double
ve ikincisi bir tarihi olarak depolaması gereken NSString
.
Amaç, tüm Sürüm 1 Etkinliklerini iki yeni varlığa aktarmak ve geçiş sırasında değerleri dönüştürmektir. Bu, ayrı bir varlıkta her biri farklı türde iki kat değerle sonuçlanır.
Geçiş yapmak için elle geçişi seçiyoruz ve bunu haritalama modelleri ile yapıyoruz. Bu aynı zamanda sorunuzun cevabının ilk kısmıdır. Taşıma işlemini iki adımda yapacağız, çünkü 2 bin girişi taşımak uzun sürüyor ve bellek ayak izini düşük tutmak istiyoruz.
Hatta devam edip bu eşleme modellerini yalnızca varlık aralıklarını taşımak için daha da bölebilirsiniz. Bir milyon kaydımız olduğunu varsayalım, bu tüm süreci çökertebilir. Getirilen varlıkları bir Filtre koşulu ile daraltmak mümkündür .
İki haritalama modelimize geri dönün.
İlk haritalama modelini şu şekilde oluşturuyoruz:
1. Yeni Dosya -> Kaynak -> Eşleme Modeli
2. Bir ad seçin, StepOne'ı seçtim
3. Kaynak ve hedef veri modelini ayarlayın
Eşleme Modeli Adım Bir
Çoklu geçiş geçişi özel varlık taşıma politikalarına ihtiyaç duymaz, ancak bu örnek için biraz daha fazla ayrıntı elde etmek için yapacağız. Bu yüzden varlığa özel bir politika ekliyoruz. Bu her zaman bir alt sınıfıdır NSEntityMigrationPolicy
.
Bu politika sınıfı, geçişimizi gerçekleştirmek için bazı yöntemler uygular. Sadece bir yöntemi uygulamak zorunda kalacak, böylece Ancak bu durumda basit: createDestinationInstancesForSourceInstance:entityMapping:manager:error:
.
Uygulama şöyle görünecek:
StepOneEntityMigrationPolicy.m
#import "StepOneEntityMigrationPolicy.h"
@implementation StepOneEntityMigrationPolicy
- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance
entityMapping:(NSEntityMapping *)mapping
manager:(NSMigrationManager *)manager
error:(NSError **)error
{
NSManagedObject *newObject =
[NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName]
inManagedObjectContext:[manager destinationContext]];
NSDate *date = [sInstance valueForKey:@"timeStamp"];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[newObject setValue:[dateFormatter stringFromDate:date] forKey:@"printedDate"];
[dateFormatter release];
[manager associateSourceInstance:sInstance withDestinationInstance:newObject forEntityMapping:mapping];
return YES;
}
Son adım: geçişin kendisi
Neredeyse aynı olan ikinci haritalama modelini kurma kısmını atlayacağım, sadece bir timeIntervalSince1970 NSDate'i bir double'a dönüştürmek için kullanılır.
Son olarak göçü tetiklememiz gerekiyor. Şimdilik standart kodu atlayacağım. İhtiyacın olursa, buraya göndereceğim. Geçiş İşlemini Özelleştirme bölümünde bulunabilir, bu sadece ilk iki kod örneğinin bir birleşimidir. Aşağıdaki gibi üçüncü ve son bölümü değiştirilmiş olacaktır: Yerine sınıf yöntemi kullanarak NSMappingModel
sınıfın mappingModelFromBundles:forSourceModel:destinationModel:
biz kullanacağız initWithContentsOfURL:
sınıf yöntemi yalnızca bir tane paketteki belki ilk, bulunan haritalama modeli dönecektir çünkü.
Şimdi döngünün her geçişinde kullanılabilen ve taşıma yöntemini taşıma yöneticisine gönderen iki eşleme modelimiz var. Bu kadar.
NSArray *mappingModelNames = [NSArray arrayWithObjects:@"StepOne", @"StepTwo", nil];
NSDictionary *sourceStoreOptions = nil;
NSURL *destinationStoreURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataMigrationNew.sqlite"];
NSString *destinationStoreType = NSSQLiteStoreType;
NSDictionary *destinationStoreOptions = nil;
for (NSString *mappingModelName in mappingModelNames) {
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:mappingModelName withExtension:@"cdm"];
NSMappingModel *mappingModel = [[NSMappingModel alloc] initWithContentsOfURL:fileURL];
BOOL ok = [migrationManager migrateStoreFromURL:sourceStoreURL
type:sourceStoreType
options:sourceStoreOptions
withMappingModel:mappingModel
toDestinationURL:destinationStoreURL
destinationType:destinationStoreType
destinationOptions:destinationStoreOptions
error:&error2];
[mappingModel release];
}
Notlar
Bir eşleme modeli cdm
pakette biter .
Hedef deponun sağlanması gerekir ve kaynak depo olmamalıdır. Başarılı bir geçişten sonra eskisini silebilir ve yenisini yeniden adlandırabilirsiniz.
Haritalama modellerini oluşturduktan sonra veri modelinde bazı değişiklikler yaptım, bu bazı uyumluluk hatalarıyla sonuçlandı ve bunları yalnızca eşleme modellerini yeniden oluşturarak çözebildim.