当 iPhone 的 Appstore 上的应用程序版本更改时,sqlite 数据库更新

Posted

技术标签:

【中文标题】当 iPhone 的 Appstore 上的应用程序版本更改时,sqlite 数据库更新【英文标题】:sqlite database update when app version changes on Appstore in iPhone 【发布时间】:2015-06-24 14:40:58 【问题描述】:

我在应用商店有一个版本为 1.0 的应用,它使用 sqlite 数据库读取数据。现在我想通过更新数据库文件将我的版本更新到 1.1。在安装时使用开发人员证书设备上的应用程序它没有更新数据库,因为数据库文件已经存在于文档文件夹中,所以我必须手动删除应用程序并重新安装它。我的问题是,当任何用户更新应用程序时,数据库也会得到根据当前版本更新。欢迎提出任何建议。谢谢

【问题讨论】:

数据是只读的还是读/写的? 【参考方案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 获取以前的应用版本号(如果存在)并将其与当前版本进行比较。

如果以前的应用程序版本&lt; 高于当前版本或以前的版本为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;

【讨论】:

以上是关于当 iPhone 的 Appstore 上的应用程序版本更改时,sqlite 数据库更新的主要内容,如果未能解决你的问题,请参考以下文章

从 iPhone 应用程序链接 appStore 中的开发人员页面

归档 iphone 时应用程序大小翻倍

iPad App Store 链接未显示 iPhone 应用程序

Phonegap 应用程序提交到 AppStore - ITMS-9000 错误

苹果手机怎么删除系统

iOS(iPhone)应用程序与ipad兼容。但是怎么样?