2013-04-25 26 views
9

Eski çekirdek veri modelim alanına sahiptir ve bu kodu NSNumber olarak değiştirmek istiyorum. Apple belgelerine ve SO üzerinde birkaç benzer sorular ve diğer bloglar (söz sonundaki referanslara bakınız) okumakÇekirdek verileri özel geçiş

Ama ne olursa olsun, ben de aynı hatayı almaya devam:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Mismatch between mapping and source/destination models'

Ben sadece var Modelin 2 sürümü ve zaman ve tekrar doğruladı kaynak ve hedef modelleri doğru.

Tüm değişikliklerimi iptal ettim ve yeni bir model, eşleştirmeler ve nesneler (NSManagedObject alt sınıflar) yeniden oluşturdum. Neredeyse 2 gün boyunca bunun üzerinde sıkışıp kaldım ve yaptığım şey hakkında hiçbir fikrim yok. Yanlış yaptığım herhangi bir işaretçi büyük takdir edilecektir.

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 
    if (_persistentStoreCoordinator != nil) { 
     return _persistentStoreCoordinator; 
    } 

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Old.sqlite"]; 

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

    NSString *sourceStoreType = NSSQLiteStoreType; 
    NSURL *sourceStoreURL = storeURL; 

    NSURL *destinationStoreURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"New.sqlite"]; 
    NSString *destinationStoreType = NSSQLiteStoreType; 
    NSDictionary *destinationStoreOptions = nil; 

    NSDictionary *sourceMetadata = 
    [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:sourceStoreType 
                   URL:sourceStoreURL 
                  error:&error]; 

    if (sourceMetadata == nil) { 
     NSLog(@"source metadata is nil"); 
    } 

    NSManagedObjectModel *destinationModel = [_persistentStoreCoordinator managedObjectModel]; 
    BOOL pscCompatibile = [destinationModel 
          isConfiguration:nil 
          compatibleWithStoreMetadata:sourceMetadata]; 

    if (pscCompatibile) { 
     // no need to migrate 
     NSLog(@"is compatible"); 
    } else { 
     NSLog(@"is not compatible"); 

     NSManagedObjectModel *sourceModel = 
     [NSManagedObjectModel mergedModelFromBundles:nil 
            forStoreMetadata:sourceMetadata]; 

     if (sourceModel != nil) { 
      NSLog(@"source model is not nil"); 

      NSMigrationManager *migrationManager = 
      [[NSMigrationManager alloc] initWithSourceModel:sourceModel 
              destinationModel:destinationModel]; 

      NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"MyMigrationMapping" withExtension:@"cdm"]; 
      NSMappingModel *mappingModel = [[NSMappingModel alloc] initWithContentsOfURL:fileURL]; 

      NSArray *newEntityMappings = [NSArray arrayWithArray:mappingModel.entityMappings]; 
      for (NSEntityMapping *entityMapping in newEntityMappings) { 
       entityMapping.entityMigrationPolicyClassName = NSStringFromClass([ConvertDateToNumberTransformationPolicy class]); 
      } 
      mappingModel.entityMappings = newEntityMappings; 

      BOOL ok = [migrationManager migrateStoreFromURL:sourceStoreURL 
                 type:sourceStoreType 
                options:nil 
              withMappingModel:mappingModel 
              toDestinationURL:destinationStoreURL 
              destinationType:destinationStoreType 
             destinationOptions:nil 
                 error:&error]; 

      if (ok) { 
       storeURL = destinationStoreURL; 
      } 
     } else { 
      NSLog(@"e nil source model"); 
     } 
    } 

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
          [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, 
          nil]; 

    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     abort(); 
    }  

    return _persistentStoreCoordinator; 
} 

Benim özel NSEntityMigration sınıfı:


- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance 
             entityMapping:(NSEntityMapping *)mapping 
              manager:(NSMigrationManager *)manager 
               error:(NSError **)error 
{ 
    // Create a new object for the model context 
    NSManagedObject *newObject = 
    [NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName] 
            inManagedObjectContext:[manager destinationContext]]; 

    NSArray *arrayOfKeys = @[@"startDate", @"endDate", @"creationTime", @"timeStamp"]; 

    for (NSString *key in arrayOfKeys) { 
     // do our transfer of NSDate to NSNumber 
     NSDate *date = [sInstance valueForKey:key]; 
     NSLog(@"Key: %@, value: %@", key, [date description]); 

     // set the value for our new object 
     [newObject setValue:[NSNumber numberWithDouble:[date timeIntervalSince1970]] forKey:key]; 
    } 

    // do the coupling of old and new 
    [manager associateSourceInstance:sInstance withDestinationInstance:newObject forEntityMapping:mapping]; 

    return YES; 
} 

Bazı referanslar:

  1. Example or explanation of Core Data Migration with multiple passes?
  2. Core Data - Default Migration (Manual)
  3. http://www.preenandprune.com/cocoamondo/?p=468
  4. http://www.timisted.net/blog/archive/core-data-migration/
+0

@Nishant com.apple.CoreData.MigrationDebug tercihini 1 olarak ayarlamayı denediniz mi? – Willeke

+0

@Willeke Evet Bunu yaptım. Açıkça bana bu eşleşmelerin neden eşlemeler arasında olduğunu anlatmıyor. – Nishant

+0

Buradan neden hata gördüğünüzü söylemek çok zor. Yeni bir soru sorun ve veri modeline ne değiştirdiğinizi, varsayılan haritalama modeline ne değiştirdiğinizi, kodda yaptığınız şeyi ve benzer sorunun ne olduğunu anlatın. – Willeke

cevap

1

Bu sorunun nedenini anlamıyorum. Taşıma işleminde, kuruluş başına bir politikam var ve kullanmadan önce varlığı kontrol ediyorum. yapıyorsun

- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance 
            entityMapping:(NSEntityMapping *)mapping 
             manager:(NSMigrationManager *)manager 
              error:(NSError **)error { 

    NSEntityDescription *sourceInstanceEntity = [sInstance entity]; 
    if ([[sInstance name] isEqualToString:@"<-name-of-entity>"]) { 
     newObject = [NSEntityDescription insertNewObjectForEntityForName:@"<-name-of-entity>" 
         inManagedObjectContext:[manager destinationContext]]; 
     NSArray *arrayOfKeys = @[@"startDate", @"endDate", @"creationTime", @"timeStamp"]; 

     for (NSString *key in arrayOfKeys) { 
      // do our transfer of NSDate to NSNumber 
      NSDate *date = [sInstance valueForKey:key]; 
      NSLog(@"Key: %@, value: %@", key, [date description]); 

      // set the value for our new object 
      [newObject setValue:[NSNumber numberWithDouble:[date timeIntervalSince1970]] forKey:key]; 
     } 
    } 

// do the coupling of old and new 
[manager associateSourceInstance:sInstance withDestinationInstance:newObject forEntityMapping:mapping]; 

return YES; 

}

+0

Olaf'ı denediğiniz için teşekkür ederiz. Şemada her varlık için bireysel taşıma politikaları oluşturmuş olmama rağmen, söylediklerinizi denedim ve hala çalışmıyor. – Neo

+0

Bu işi almayı başardınız mı? –

+0

@Neo, bunu henüz çözdünüz mü? –

1

Her şey olması gerekenden çok daha fazla karmaşıktır: Bu ekstra if size yardımcı olacaktır emin değilim. Tüm bunları veritabanına hiç taşımadan yapabilirsiniz. Bunu uygulayan alt sınıfa başka özelliği ekleyebilirsiniz:

///in your .h 
@property(nonatomic, copy) NSNumber* startDateNumber 
/// in you .m 
-(NSNumber*) startDateNumber{ 
    if (self.startDate) { 
     return @(self.startDate.timeIntervalSince1970); 
    } 
    return nil; 
} 
-(void)setStartDateNumber:(NSNumber*)startDateNumber{ 
    if(startDateNumber){ 
     self.startDate =[NSDate dateWithTimeIntervalSince1970:startDateNumber.doubleValue]; 
    }else{ 
     self.startDate = nil; 
    } 
} 

yinelenen özelliklerini (startDate ve startDateNumber) olması biraz can sıkıcı ama çok basittir ve göç sorunlardan herhangi yoktur.

+0

Bu, kullandığım anıtsal Çekirdek veri modelinin yalnızca bir örneğidir. Bu nedenle, çok geçişli geçişleri kullanarak veritabanını doğru bir şekilde taşımak için anlamaya gerek. – Nishant

İlgili konular