Я только что провел несколько дней, борясь с этой ошибкой, а также с ошибками mergedModelFromBundles и получая сообщение об ошибке «Не удается объединить модели с двумя разными сущностями с именем *».
Оказалось, что основная проблема заключалась в том, чтоXcode не удаляет старые ресурсы с устройств, и у меня были старые версии моей модели данных (файлы .mom), которые вызывали конфликты.Вот почему удаление приложения устранило проблему на одном из моих устройств.
После поиска этого сообщения в блоге с помощью другого SO-ответа я сделал свое приложение более терпимым к старым моделям, изменив эту строку, котораяищет ВСЕ файлы .mom:
NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
для этого, который ищет только в каталоге Filters:
NSString *path = [[NSBundle mainBundle] pathForResource:@"Filters" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
Я использовал recursivePathsForResourcesOfType из thisпоэтому вопрос : чтобы помочь выяснить это, зарегистрировав все файлы .mom в приложении:
NSArray *momPaths = [self recursivePathsForResourcesOfType:@"mom" inDirectory:[[NSBundle mainBundle] resourcePath]];
NSLog(@"All .mom files:%@",momPaths);
Я также использовал iExplorer , чтобы посмотреть на посторонние файлы .mom(Я еще не пытался их удалить).
Метод ниже также был полезен.Это показало, что сущность была в объединенной модели, возвращенной [psc managedObjectModel], которой больше не существует ни в одной из моих моделей или в самом магазине.Это было то, что позволило мне полагать, что старая модель кэшировалась на самом устройстве, которое чистое здание не удаляло.Метод регистрирует каждый объект, который является таким же, был изменен, добавлен или удален из модели.(записывается с этим SO-ответом в качестве отправной точки):
- (BOOL)comparePersistentStore:(NSPersistentStoreCoordinator *)psc withStoreURL: (NSURL *)storeURL {
NSError *error = nil;
// Get the entities & keys from the persistent store coordinator
NSManagedObjectModel *pscModel = [psc managedObjectModel];
NSDictionary *pscEntities = [pscModel entitiesByName];
NSSet *pscKeys = [NSSet setWithArray:[pscEntities allKeys]];
//NSLog(@"psc model:%@", pscModel);
//NSLog(@"psc keys:%@", pscKeys);
NSLog(@"psc contains %d entities", [pscModel.entities count]);
// Get the entity hashes from the storeURL
NSDictionary *storeMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType
URL:storeURL
error:&error];
NSDictionary *storeHashes = [storeMetadata objectForKey:@"NSStoreModelVersionHashes"];
//NSLog(@"store metadata:%@", sourceMetadata);
NSLog(@"store URL:%@", storeURL);
NSLog(@"store NSStoreUUID:%@", [storeMetadata objectForKey:@"NSStoreUUID"]);
NSLog(@"store NSStoreType:%@", [storeMetadata objectForKey:@"NSStoreType"]);
NSSet *storeKeys = [NSSet setWithArray:[storeHashes allKeys]];
// Determine store entities that were added, removed, and in common (to/with psc)
NSMutableSet *addedEntities = [NSMutableSet setWithSet:pscKeys];
NSMutableSet *removedEntities = [NSMutableSet setWithSet:storeKeys];
NSMutableSet *commonEntities = [NSMutableSet setWithSet:pscKeys];
NSMutableSet *changedEntities = [NSMutableSet new];
[addedEntities minusSet:storeKeys];
[removedEntities minusSet:pscKeys];
[commonEntities minusSet:removedEntities];
[commonEntities minusSet:addedEntities];
// Determine entities that have changed (with different hashes)
[commonEntities enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) {
NSData *storeHash = [storeHashes objectForKey:key];
NSEntityDescription *pscDescrip = [pscEntities objectForKey:key];
if ( ! [pscDescrip.versionHash isEqualToData:storeHash]) {
if (storeHash != nil && pscDescrip.versionHash != nil) {
[changedEntities addObject:key];
}
}
}];
// Remove changed entities from common list
[commonEntities minusSet:changedEntities];
if ([commonEntities count] > 0) {
NSLog(@"Common entities:");
[commonEntities enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) {
NSData *storeHash = [storeHashes objectForKey:key];
NSEntityDescription *pscDescrip = [pscEntities objectForKey:key];
NSLog(@"\t%@:\t%@", key, pscDescrip.versionHash);
}];
}
if ([changedEntities count] > 0) {
NSLog(@"Changed entities:");
[changedEntities enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) {
NSData *storeHash = [storeHashes objectForKey:key];
NSEntityDescription *pscDescrip = [pscEntities objectForKey:key];
NSLog(@"\tpsc %@:\t%@", key, pscDescrip.versionHash);
NSLog(@"\tstore %@:\t%@", key, storeHash);
}];
}
if ([addedEntities count] > 0) {
NSLog(@"Added entities to psc model (not in store):");
[addedEntities enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) {
NSEntityDescription *pscDescrip = [pscEntities objectForKey:key];
NSLog(@"\t%@:\t%@", key, pscDescrip.versionHash);
}];
}
if ([removedEntities count] > 0) {
NSLog(@"Removed entities from psc model (exist in store):");
[removedEntities enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) {
NSData *storeHash = [storeHashes objectForKey:key];
NSLog(@"\t%@:\t%@", key, storeHash);
}];
}
BOOL pscCompatibile = [pscModel isConfiguration:nil compatibleWithStoreMetadata:storeMetadata];
NSLog(@"Migration needed? %@", pscCompatibile?@"no":@"yes");
return pscCompatibile;
}
использование: вызывается перед добавлением каждого хранилища в NSPersistentStoreCoordinator:
[self comparePersistentStore:self.psc withStoreURL:self.iCloudStoreURL];
_iCloudStore = [self.psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:self.iCloudStoreURL
options:options
error:&localError];