【问题标题】:sqlite database update when app version changes on Appstore in iPhone当 iPhone 的 Appstore 上的应用程序版本更改时,sqlite 数据库更新
【发布时间】:2023-03-24 07:35:02
【问题描述】:
我在应用商店有一个版本为 1.0 的应用,它使用 sqlite 数据库读取数据。
现在我想通过更新数据库文件将我的版本更新到 1.1。
在安装时使用开发人员证书设备上的应用程序它没有更新数据库,因为数据库文件已经存在于文档文件夹中,所以我必须手动删除应用程序并重新安装它。
我的问题是,当任何用户更新应用程序时,数据库也会得到根据当前版本更新。
欢迎提出任何建议。
谢谢
【问题讨论】:
标签:
iphone
ios
xcode
sqlite
app-store
【解决方案1】:
我确信有很多方法可以做到这一点(还有很多比我的更好的方法),但我处理此类问题的方式如下:
首先,我在应用程序的第一个 .h 文件(将首先加载的文件)中定义一个常量来指示首次加载并将其设置为 0:
#define FirstTime 0
现在您必须知道我打算将此常量的值保存在 Documents 文件夹中以供将来参考,因此我使用共享数据实例。在viewDidLoad 我做了以下测试:
//if first time run of this version
if( [MyDataModel sharedInstance].count < (FirstTime + 1) )
{
//do what you need to do as the first time load for this version
[MyDataModel sharedInstance].count++
//save the count value to disk so on next run you are not first time
//this means count = 1
}
现在关键在于您的新应用版本(比如 1.1)。我将FirstTime 更改为 2:
#define FirstTime 2
由于磁盘上保存的 First Time 值为 1,这意味着您将被上面的 if 语句捕获,因此您可以在其中执行任何您想做的事情,例如删除旧表并使用新格式重新创建它们。
再次没有那么出色,但解决了这个案子!
【解决方案2】:
您也可以使用.plist:
- (void)isItTheFirstTimeAfterUpdate {
NSString *versionnum;
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"yourplist.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if(![fileManager fileExistsAtPath:path]) {
NSString *bundle = [[NSBundle mainBundle] pathForResource:@"yourplist" ofType:@"plist"];
[fileManager copyItemAtPath:bundle toPath:path error:&error];
}
NSMutableDictionary *savedStock = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
versionnum = @"";
//it can be installed by user (for ex. it is 1.3 but first installed), no plist value is set before
if(([savedStock objectForKey:@"versionnum"]) && (![[savedStock objectForKey:@"versionnum"] isEqualToString:@""])){
versionnum = [savedStock objectForKey:@"versionnum"];
}
//to get the version of installed/updated-current app
NSString *myversion = [NSString stringWithFormat:@"%@",[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]];
//if no version has been set-first install- or my version is the latest version no need to do sth.
if ([versionnum isEqualToString:myversion] || [versionnum isEqualToString:@""]) {
NSLog(@"Nothing has to be done");
}
else {
[self cleanDB];//i have clean tables and create my new db tables maybe logout the user etc.
[savedStock setObject:[NSString stringWithString:myversion] forKey:@"versionnum"];//setting the new version
[savedStock writeToFile:path atomically:YES];
}
}
您可以在应用程序启动或主视图控制器的视图控制器中调用该函数.. 您的选择。
希望对你有帮助。
【解决方案3】:
这种方法依赖于NSUserDefaults。我们的想法是从NSUserDefaults 获取以前的应用版本号(如果存在)并将其与当前版本进行比较。
如果以前的应用程序版本< 高于当前版本或以前的版本为nil,则代码执行数据库升级。这意味着即使应用程序已经在 AppStore 上发布,也可以使用这种方法。它会在应用更新期间将数据库升级到新版本。
这是一个 plist 文件:
有一个数组,由版本号和对应升级版本的一组sql查询组成。
假设以前的版本是 1.2,实际版本是 1.4,代码只执行从 1.2 到 1.4 的升级。如果以前的版本是 1.3,而当前的版本是 1.4,则代码只执行从 1.3 到 1.4 的升级。
如果之前的版本为 nil,则代码执行升级到 1.1,然后升级到 1.2,然后升级到 1.3,最后升级到 1.4。
NSString * const VERSION_KEY = @"version";
-(void)upgradeDatabaseIfRequired{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *previousVersion=[defaults objectForKey:VERSION_KEY];
NSString *currentVersion=[self versionNumberString];
if (previousVersion==nil || [previousVersion compare: currentVersion options: NSNumericSearch] == NSOrderedAscending) {
// previous < current
//read upgrade sqls from file
NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"UpgradeDatabase" ofType:@"plist"];
NSArray *plist = [NSArray arrayWithContentsOfFile:plistPath];
if (previousVersion==nil) {//perform all upgrades
for (NSDictionary *dictionary in plist) {
NSString *version=[dictionary objectForKey:@"version"];
NSLog(@"Upgrading to v. %@", version);
NSArray *sqlQueries=[dictionary objectForKey:@"sql"];
while (![DB executeMultipleSql:sqlQueries]) {
NSLog(@"Failed to upgrade database to v. %@, Retrying...", version);
};
}
}else{
for (NSDictionary *dictionary in plist) {
NSString *version=[dictionary objectForKey:@"version"];
if ([previousVersion compare: version options: NSNumericSearch] == NSOrderedAscending) {
//previous < version
NSLog(@"Upgrading to v. %@", version);
NSArray *sqlQueries=[dictionary objectForKey:@"sql"];
while (![DB executeMultipleSql:sqlQueries]) {
NSLog(@"Failed to upgrade database to v. %@, Retrying...", version);
};
}
}
}
[defaults setObject:currentVersion forKey:VERSION_KEY];
[defaults synchronize];
}
}
- (NSString *)versionNumberString {
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString *majorVersion = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
return majorVersion;
}