我在AppStore上有一个应用程序,它是在12月13日使用Xcode 4.3提交的,它有一个核心数据模型(版本2)。我现在将发布下一个版本,它更新了核心数据模型。当我在调试模式下运行代码时,迁移工作正常。但是当我通过TestFlight发布一个版本时,迁移失败了,我得到了下面的错误。出于安全考虑,每次应用程序退出时,我都会删除数据库(我保存了一个加密副本),在下一次启动时,我会解密这个DB。
用于初始化PersistentStoreCoordinator的代码。
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSDictionary *options = @{
NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES
};
// Check if we need a migration
NSDictionary *sourceMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType URL:storeURL error:&error];
NSManagedObjectModel *destinationModel = [_persistentStoreCoordinator managedObjectModel];
BOOL isModelCompatible = (sourceMetadata == nil) || [destinationModel isConfiguration:nil compatibleWithStoreMetadata:sourceMetadata];
if (! isModelCompatible) {
// We need a migration, so we set the journal_mode to DELETE
options = @{NSMigratePersistentStoresAutomaticallyOption:@YES,
NSInferMappingModelAutomaticallyOption:@YES,
NSSQLitePragmasOption: @{@"journal_mode": @"DELETE"}
};
}
NSPersistentStore *persistentStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error];
if (! persistentStore) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documents = [paths objectAtIndex:0];
NSString *databasePath = [documents stringByAppendingPathComponent:@"Store"];
NSString *sqlite = [databasePath stringByAppendingPathComponent:@"myDatabase.sqlite"];
[[NSFileManager defaultManager] removeItemAtPath:sqlite error:nil];
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
//abort();
}
// Reinstate the WAL journal_mode
if (! isModelCompatible) {
[_persistentStoreCoordinator removePersistentStore:persistentStore error:NULL];
options = @{NSMigratePersistentStoresAutomaticallyOption:@YES,
NSInferMappingModelAutomaticallyOption:@YES,
NSSQLitePragmasOption: @{@"journal_mode": @"WAL"}
};
[_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error];
}
return _persistentStoreCoordinator;
当我尝试初始化persistentStoreCoordinator时,我会得到下面的错误。
未解决的错误错误Domain=NSCocoaErrorDomain Code=259“操作无法完成。(可可错误259。)UserInfo=0x15df4dc0 {路径处的NSUnderlyingException=File似乎不是SQLite数据库:NSUnderlyingException=File{
NSUnderlyingException = "File at path does not appear to be a SQLite database: /var/mobile/Applications/9B623099-5591-4C55-BA83-77A057B94690/Documents/Store/myDatabase.sqlite";}
奇怪的是,在iOS7.0.6上,升级场景在Dev和发行版配置上都工作得很好,但是在iOS7.1上似乎只适用于Dev配置。我已经厌倦了删除WAL和SHM文件以及,但没有任何效果。
发布于 2014-06-19 04:44:47
这里的错误信息很能说明问题。上面写着:
NSUnderlyingException = "File at path does not appear to be a SQLite database: /var/mobile/Applications/9B623099-5591-4C55-BA83-77A057B94690/Documents/Store/myDatabase.sqlite";}
我在想,这可能是由于更新的核心数据sqlite和WAL文件之间的不匹配,但结果发现,这个错误更多的是由于加解密过程中的密钥不匹配。这是我的第一次猜测,我已经让我的同事检查了这个,但是他以某种方式证实了这一点,而我们不同意这个理论。
我们的加密方法是将运行时生成的加密密钥保存到密钥链中。现在的前提是,在应用程序升级之前和升级之后,密钥链中的值仍然存在。然而,由于使用了错误的捆绑标识符,升级后的应用程序没有从密钥链中获得值,而是创建了自己的运行时值。
存储在密钥链中的值只有在完整的包标识符相同的情况下才能在应用程序和应用程序更新之间共享。
BundleIdentifierPrefix1.com.yourcompany.appname的包标识符app1应用1.1有包标识符为BundleIdentifierPrefix2.com.yourcompany.appname
由于反向域相同,应用程序是作为更新安装的,但是由于前缀不同,密钥链值没有共享。
https://stackoverflow.com/questions/24164906
复制相似问题