我正在尝试为我的应用程序实现一个流程,以便在需要时更新应用程序,并且更新我的意思是在设备中下载更新的应用程序 .ipa。
问题是我使用 CoreData 来存储第一次启动时带来的服务器数据,并且在旧版本和新版本之间,我已经将一些实体和一些旧实体的属性添加到数据库中。这会产生冲突,因为我不知道如何处理迁移和/或任何可以让我在结构发生变化时重新创建数据库的能力。
目前,如果我更新具有相同数据库结构的应用程序,该应用程序可以正常工作,但如果我修改它,应用程序会崩溃,如预期的那样。
有什么想法吗?
如果您只添加了一些实体/属性,您可以使用 CoreData 轻量级迁移:
1) 在打开 xcdatamodeld 文件的情况下,从编辑器菜单添加新版本的模式。
2) 将新实体属性添加到此新模式版本。
3)在您的 xcdatamodeld 选项(左窗格)中将新模式版本设置为活动版本。
4)在 UIApplicationDelegate 中的 persistentStore 初始化方法中设置NSMigratePersistentStoresAutomaticallyOption和为 true。NSInferMappingModelAutomaticallyOption
您现在应该可以运行该应用程序了。架构应自动更新以匹配您的新数据库结构。这也将保留数据库内容,清空它可能是您想要在代码中执行的操作,检测新版本的首次启动。
如果可以从服务器重新创建/下载应用程序中的数据,那么这是一个很好的解决方案。据我了解,您正在从服务器获取数据,这是一个很好的案例,这意味着可以在新数据库中重新创建旧数据。您不需要设置迁移堆栈,有一个非常快速的解决方案。诀窍是删除旧的 sqlite 数据库并创建一个新数据库。
这是我在应用程序更新中使用的代码。您需要将其添加到您的 AppDelegate.m
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"YourDatabase.sqlite"];
NSManagedObjectModel *managedObjectModel = [self managedObjectModel];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: managedObjectModel];
// 检查我们是否已经有一个持久存储
if ( [[NSFileManager defaultManager] fileExistsAtPath: [storeURL path]] ) {
NSDictionary *existingPersistentStoreMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType: NSSQLiteStoreType URL: storeURL error: &error];
如果(!existingPersistentStoreMetadata){
// 持久存储发生了*真的*糟糕的事情
//[NSException raise: NSInternalInconsistencyException format: @"Failed to read metadata for persistent store %@: %@", storeURL, error];
NSLog(@"读取持久存储 %@ 的元数据失败:%@", storeURL, error);
}
if ( ![managedObjectModel isConfiguration: nil compatibleWithStoreMetadata: existingPersistentStoreMetadata] ) {
if ( ![[NSFileManager defaultManager] removeItemAtURL: storeURL error: &error] )
NSLog(@"*** 无法删除持久化存储,%@", 错误);
} // 否则现有的持久存储与当前模型兼容 - 很好!
} // 否则还没有数据库文件
[_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
配置:无
网址:商店网址
选项:无
错误:&错误];
返回_persistentStoreCoordinator;
}
此代码涵盖问题
只需将 @"YourDatabase.sqlite" 更改为您的 sqliteDB 文件名,它就可以正常工作。