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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8794397/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 22:56:47  来源:igfitidea点击:

sqlite database update when app version changes on Appstore in iPhone

iphoneiosxcodesqliteapp-store

提问by Manish Agrawal

I have an app with version 1.0 on app store which uses sqlite database for reading the data.
Now I want to update my version to 1.1 with update in database file.
While using developer certificate when I install app on device it did not update the database as the database file already exist in documents folder so i have to manually delete the app and install it again.
My question is, when any user update the app, will the database also get updated according the current version.
Any suggestions are welcome.
Thanks

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

采纳答案by antf

I am sure there are many ways to do this (and many ways better then mine as well), but the way that I handle such problems is as follows:

我相信有很多方法可以做到这一点(而且很多方法也比我的好),但我处理这些问题的方式如下:

First I define a constant in the first .h file of the app (the one that will load first) to indicate First Time load and set it to 0:

首先,我在应用程序的第一个 .h 文件(将首先加载的文件)中定义一个常量来指示首次加载并将其设置为 0:

#define FirstTime 0

Now you have to know that I have the intention to save the value of this constant in the Documents folder for future references, therefore I use a Shared Data Instance. In the viewDidLoadI do the following test:

现在您必须知道我打算将此常量的值保存在 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
}

Now the trick is on your new app version (say 1.1). I change the FirstTimeto 2:

现在诀窍在于您的新应用程序版本(比如 1.1)。我将其更改FirstTime为 2:

#define FirstTime 2

Since the saved First Time value on disc is 1 this means you will be caught by the if statement above, therefore inside it you can do anything you want like delete the old tables and recreate them again with the new formation.

由于保存在光盘上的 First Time 值为 1,这意味着您将被上面的 if 语句捕获,因此在其中您可以做任何您想做的事情,例如删除旧表并使用新格式重新创建它们。

Again not that brilliant, but solves the case!

再次不是那么出色,但解决了这个案子!

回答by Alexey

This approach relies on NSUserDefaults. The idea is to get the previous app version number(if exists) from NSUserDefaultsand compare it with the current version.

这种方法依赖于NSUserDefaults. 这个想法是从中获取以前的应用程序版本号(如果存在)NSUserDefaults并将其与当前版本进行比较。

The code performs db upgrade if the previous app version <than current version or if the previous version is nil. It means that this approach can be used even though the app was already published on the AppStore. It will upgrade database to the new version during the app update.

如果以前的应用程序版本<比当前版本高或者以前的版本是nil. 这意味着即使应用程序已经在 AppStore 上发布,也可以使用这种方法。它将在应用程序更新期间将数据库升级到新版本。

This is a plist file:

这是一个 plist 文件:

enter image description here

在此处输入图片说明

There is an array which is composed of the version number and a set of sql queries for the corresponding upgrade version. Suppose that a previous version is 1.2 and the actual version is 1.4 the code perform the upgrade only from the version 1.2 to 1.4. If the previous version is 1.3 and the current 1.4 the code performs upgrade only from 1.3 to 1.4. If the previous version is nil the code performs upgrade to 1.1 then to 1.2 then to 1.3 and finally to 1.4.

有一个数组,由版本号和对应升级版本的一组sql查询组成。假设以前的版本是 1.2 而实际版本是 1.4 代码只执行从版本 1.2 到 1.4 的升级。如果之前的版本是 1.3 而当前的 1.4 代码只执行从 1.3 到 1.4 的升级。如果以前的版本为零,则代码执行升级到 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;
}

回答by Mihriban Minaz

You can use .plistas well:

您也可以使用.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];
    }
}

And you can call the function in application launch or in your main view controller's view controller.. your choice.

您可以在应用程序启动或主视图控制器的视图控制器中调用该函数..您的选择。

hope it helps.

希望能帮助到你。