民间,
轻量级迁移在这条线路上100%的时间都失败了:
[persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]
错误:
Error: Error Domain=NSCocoaErrorDomain Code=134130 UserInfo=0x4fbff20 "Operation could not be completed. (Cocoa error 134130.)"
"Can't find model for source store";
这是我的托管对象上下文,模型和持久性存储:
- (NSManagedObjectContext *) managedObjectContext {
if (managedObjectContext != nil) {
return managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator: coordinator];
}
return managedObjectContext;
}
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
return managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Locations.sqlite"]];
NSError *error;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
// Allow inferred migration from the original version of the application.
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
NSLog(@"Error: %@",error);
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return persistentStoreCoordinator;
}
我的项目中有两个版本的模型:版本4和版本5.如果我将版本4设置为默认值,它可以正常工作。如果我选择“设计 - >数据模型 - >添加模型版本”(如this post所述),请进行更改,设计 - >数据模型 - >设置当前版本,构建和运行,它将失败,前面提到“无法找到源存储模型”错误。将模型设置回版本4,没有问题,addPersistentStoreWithType。或者,如果我添加模型版本并且不做任何更改,只需从版本4转到5而不添加任何新字段,没有问题。如果我然后尝试从5到6,上述错误。
此代码在模拟器和手机上都失败了。我阅读了几个要求删除和重新安装应用程序的处方,这对于模拟器和手机都有效,但我担心当我向真实用户发布时,它会破坏我的安装基础,因为它们将无法删除并重新安装 - App Store将自动升级它们。
此代码在过去的版本中有效,我没有任何变化 - 因此我能够将其一直升级到版本4.我最近升级到iOS4的XCode 3.2.3版本,这可能与此有关。
其他人是否像我一样突然出现这个问题?有没有人设法超越它?感谢。
PS - 对于偶然发现此页面的Google员工,以下是您可能会考虑阅读的所有相关页面。不幸的是,这些都没有解决我的问题。
更新
虽然这不是一个真正的修复,但它确实避免了崩溃客户端的情况:只需删除数据库文件:
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
// Delete file
if ([[NSFileManager defaultManager] fileExistsAtPath:storeUrl.path]) {
if (![[NSFileManager defaultManager] removeItemAtPath:storeUrl.path error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error])
{
// Handle the error.
NSLog(@"Error: %@",error);
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
更新2
以下是我检查VersionInfo.plist时发生的情况:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSManagedObjectModel_CurrentVersionName</key>
<string>Profile 5</string>
<key>NSManagedObjectModel_VersionHashes</key>
<dict>
<key>Profile</key>
<dict>
<key>Profile</key>
<data>
ZIICGgMBreuldkPXgXUhJwKamgwJzESM5FRTOUskomw=
</data>
</dict>
<key>Profile 2</key>
<dict>
<key>Profile</key>
<data>
tEB7HrETWOSUuoeDonJKLXzsxixv8ALHOoASQDUIZMA=
</data>
</dict>
<key>Profile 3</key>
<dict>
<key>Profile</key>
<data>
qyXOJyKkfQ8hdt9gcdFs7SxKmZ1JYrsXvKbtFQTTna8=
</data>
</dict>
<key>Profile 4</key>
<dict>
<key>Profile</key>
<data>
lyWDJJ0kGcs/pUOModd3Q1ymDvdRiNXui4NCpLxDFSw=
</data>
</dict>
<key>Profile 5</key>
<dict>
<key>Profile</key>
<data>
V4PyRK1ezj3xK1QFRCTVzGOqyJhEb7FRMzglrTsP0cI=
</data>
</dict>
</dict>
</dict>
</plist>
这是我编写的用于检查模型的代码(注意我必须出去添加一个base64编码器,因为这是VersionInfo.plist文件中的内容)
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:storeUrl error:&error];
NSLog(@"%@",storeMeta);
id someObj = [[storeMeta objectForKey:@"NSStoreModelVersionHashes"] objectForKey:@"Profile"];
NSLog(@"%@",someObj);
NSLog(@"%@",[NSString base64StringFromData:someObj length:[someObj length]]);
这是调试输出:
{
NSPersistenceFrameworkVersion = 310;
NSStoreModelVersionHashes = {
Profile = <97258324 9d2419cb 3fa5438c a1d77743 5ca60ef7 5188d5ee 8b8342a4 bc43152c>;
SerializedMessage = <4530863c d943479a edfb4dfb 5059c28d d6137dc4 d1153d36 ed52be49 11074f13>;
};
NSStoreModelVersionHashesVersion = 3;
NSStoreModelVersionIdentifiers = (
);
NSStoreType = SQLite;
NSStoreUUID = "823FD306-696F-4A0F-8311-2792825DC66E";
"_NSAutoVacuumLevel" = 2;
}
<97258324 9d2419cb 3fa5438c a1d77743 5ca60ef7 5188d5ee 8b8342a4 bc43152c>
lyWDJJ0kGcs/pUOModd3Q1ymDvdRiNXui4NCpLxDFSw=
正如您所看到的,以'ly'开头的最后一行与VersionInfo.plist中的Profile 4相匹配......因此我认为没有理由说它应该失败。还有其他想法吗?
答案 0 :(得分:9)
我读了几个叫处方 删除并重新安装应用程序, 哪个适用于模拟器和 电话,但我害怕当我 将它发布给真正的用户 打破我的安装基础,因为他们 将无法删除并重新安装。
这是一个问题,当Xcode没有从模拟器/ dev-device中移除旧的momc文件时,如果模型文件被更改,例如改名称。旧文件仍然会导致混淆。这是你在开发过程中只看到的东西,因为它是Xcode操纵应用程序包的方式的工件,而不是每次完全重新安装它,就像发布版本必须发生的那样。
您可以确认此记录返回:
[[NSBundle mainBundle] URLsForResourcesWithExtension:@"momc"subdirectory:nil];
...它应该显示应用程序包中所有已编译的模型文件
在开发过程中依赖迁移是不好的做法,因为如果要对模型和存储进行更改,迁移很常见。所有代码都被固定后,您应该只使用迁移。我还建议您每次运行时从头开始重新生成商店。通过更改模型很容易在商店中建立垃圾。
答案 1 :(得分:4)
我已阅读您更新的问题。模型版本变得非常混乱。
您应该尝试审核现有商店实际要求的模型版本,并尝试在运行时列出应用包中的所有可用模型。
我查看我的应用程序的模型目录
NSString *modelDirectoryPath = [[NSBundle mainBundle] pathForResource:@"MyModel" ofType:@"momd"];
我不确定开发人员是否通常这样做,但我保留了不同名称的模型版本..所以我在那里:
VersionInfo.plist
MyModel.mom
MyModel2.mom
VersionInfo.plist
中列出的版本哈希应该可以帮助您排除故障。查找现有持久性存储所需的版本哈希,看看是否可以在VersionInfo.plist
中列出的版本哈希中找到它。
实际上,我找不到一种方法来编写一些代码,这些代码会向持久性存储区询问它的实体版本哈希是什么。 NSPersistentStoreCoordinator
或NSMigrationManger
似乎是私下做的。即,他们根据加载商店的模型检查持久性商店实体版本。
还有另一个快速查看,它可以在商店元数据中找到。很好,很容易!
NSError *error;
NSURL *storeURL = [NSURL fileURLWithPath:[[self class] storePath]];
NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:storeURL error:&error];
在storeMeta
中查看
<CFString 0x7328050 [0x2724380]>{contents = "NSStoreModelVersionHashes"} = <CFBasicHash 0x7328340 [0x2724380]>{type = immutable dict, count = 5,
entries =>
0 : <CFString 0x7328110 [0x2724380]>{contents = "MyEntityNameOne"} = <CFData 0x73281b0 [0x2724380]>{length = 32, capacity = 32, bytes = 0x143325cf121239ce156af2e2a1aad7d9 ... 976977fdf29fc013}
1 : <CFString 0x7328130 [0x2724380]>{contents = "MyEntityNameTwo"} = <CFData 0x7328200 [0x2724380]>{length = 32, capacity = 32, bytes = 0x0ca6ecf1283d12bd3ca82af39b6b9f5d ... 149dd39a591e0c4d}
... }
应该很容易迭代NSStoreModelVersionHashes
字典,并记录商店所需的版本哈希值。
将其与VersionInfo.plist
中的可用内容进行手动匹配,然后查看缺少的内容。也许没有一个模型包含现有持久性存储中所有实体所需的版本。这可能是由于在设置新模型版本之前或之后模型上的(偶然?)编辑而发生的?
答案 2 :(得分:4)
我遇到了esilver的确切问题,并通过Google发现了这个问题。但是,对我有用的修复工具并不是SO上的任何其他东西(我知道),所以这里有:
如果您的捆绑包中有*.mom
个文件(编译对象模型)的多个副本,则在尝试代表您迁移时,Core Data可能会感到困惑。
我们的问题是,每个单独的模型文件(Data.xcdatamodel
,Data_V1.xcdatamodel
,Data_V2.xcdatamodel
等)不仅位于xcdatamodeld/
目录中(包含在内容中)在构建过程中编译),但每个文件也包含在“编译源”列表中。
这意味着生成的包有两组*.mom
个文件:一个在xcdatamodeld/
内,一个在顶层。我认为Core Data变得非常非常困惑,并导致了这个错误。从“编译源”中删除每个xcdatamodel
文件并离开xcdatamodeld
目录解决了我们的问题(例如,自动版本升级并再次运行)。希望这有帮助!
答案 3 :(得分:0)
在我的情况下,完全相同的事情正在发生,我在iOS 7上,这个问题至少让我头脑干了一个星期,然后终于找到适合我的解决方案 。 为了使它工作,你必须在用于添加PersistentStore的选项中添加额外的值,然后你去(我不确定其他iOS版本,但是它肯定会在iOS 7上运行)。
-(NSManagedObjectModel *)managedObjectModel
{
if (managedObjectModel != nil)
{
return managedObjectModel;
}
managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
return managedObjectModel;
}
-(NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (persistentStoreCoordinator != nil)
{
return persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"ABC.sqlite"];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] ini tWithManagedObjectModel:[self managedObjectModel]];
//Creating Lightweight migration.
NSDictionary *options =
@{
NSMigratePersistentStoresAutomaticallyOption:@YES
,NSInferMappingModelAutomaticallyOption:@YES
,NSSQLitePragmasOption: @{@"journal_mode": @"DELETE"}
};
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return persistentStoreCoordinator;
}
答案 4 :(得分:-2)
民间,
为了记录,我完全停止使用核心数据。我的代码很复杂,并且根据上述问题,不可靠。我现在直接使用SQLLite,我很高兴。我不建议在任何情况下使用Core Data。