Обновление базы данных sqlite при изменении версии приложения в Appstore на iPhone - PullRequest
19 голосов
/ 10 января 2012

У меня есть приложение с версией 1.0 в магазине приложений, которое использует базу данных sqlite для чтения данных.
Теперь я хочу обновить свою версию до 1.1 с обновлением в файле базы данных.
При использовании сертификата разработчика, когда Я устанавливаю приложение на устройство, оно не обновляло базу данных, поскольку файл базы данных уже существует в папке документов, поэтому мне нужно вручную удалить приложение и установить его снова.
Мой вопрос: когда любой пользователь обновит приложение, База данных также обновляется в соответствии с текущей версией.
Любые предложения приветствуются.
Спасибо

Ответы [ 3 ]

15 голосов
/ 10 января 2012

Я уверен, что есть много способов сделать это (и намного лучше, чем мой), но способ решения таких проблем заключается в следующем:

Сначала я определяю константу в первом .h файле приложения (тот, который будет загружаться первым), чтобы указать загрузку в первый раз, и устанавливаю ее в 0:

#define FirstTime 0

Теперь вы должны знать, что у меня есть намерение сохранить значение этой константы в папке «Документы» для будущих ссылок, поэтому я использую экземпляр общих данных. В 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

Поскольку сохраненное значение «Первый раз» на диске равно 1, это означает, что вы будете замечены оператором if выше, поэтому внутри него вы можете делать все, что захотите, например, удалять старые таблицы и воссоздавать их снова с новым формированием.

Опять не так уж блестяще, но решает дело!

12 голосов
/ 15 октября 2013

Этот подход основан на NSUserDefaults. Идея состоит в том, чтобы получить предыдущий номер версии приложения (если существует) из NSUserDefaults и сравнить его с текущей версией.

Код выполняет обновление базы данных, если предыдущая версия приложения <, чем текущая версия, или если предыдущая версия nil. Это означает, что этот подход можно использовать, даже если приложение уже было опубликовано в AppStore. Он обновит базу данных до новой версии во время обновления приложения.

Это файл plist:

enter image description here

Существует массив, который состоит из номера версии и набора 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;
}
6 голосов
/ 13 августа 2012

Вы также можете использовать .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];
    }
}

И вы можете вызывать эту функцию при запуске приложения или в контроллере представления вашего основного контроллера. На ваш выбор.

надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...